模板左值右值的转换
/**
* 功能:模板左值右值的转换
* 时间:2014年7月27日08:18:06
* 作者:cutter_point
*/
#include<iostream>
#include<algorithm>
#include<utility>
using namespace std;
template<typename It>
auto fcn(It beg, It end) -> typename remove_reference<decltype(*beg)>::type
{
return *beg; //这里返回的是beg的一个拷贝,因为用了remove_reference去除了引用
}
/**************************************
Function Pointers and Argument Deduction
**************************************/
template<typename T>
int compare(const T &, const T &){cout<<"template<typename T>int compare(const T &, const T &)"<<endl;}
//分别实例化成int compare(const string &, const string &)作为func的参数
void func(int(*)(const string &, const string &)){cout<<"void func(int(*)(const string &, const string &))"<<endl;}
//分别实例化成int compare(const int &, const int &)作为func的参数
void func(int(*)(const int &, const int &)){cout<<"void func(int(*)(const int &, const int &))"<<endl;}
void fun1()
{
int (*pf1)(const int &, const int &)=compare; //吧compare实例化成int compare(const int &, const int &)
func(compare<int>);
}
/**************************************
Template Argument Deduction and References
**************************************/
/**
Type Deduction from Lvalue Reference Function Parameters
*/
/*
见word文档
*/
/**
Type Deduction from Rvalue Reference Function Parameters
*/
/*
见word文档
*/
/**
Writing Template Functions with Rvalue Reference Parameters
写一个模板函数带有右值引用参数
*/
template<typename T>
T fcn2(T &t)
{
cout<<"t的值是:"<<t<<endl;
return t;
}
template<typename T>
void f3(T &&val)
{
T t=val;
t=fcn2(t);
if(val == t)
{
cout<<"void f3(T &&val),val == t"<<endl;
}
}
/**************************************
Understanding std::move
**************************************/
/**
std::move如何定义
*/
//remove_reference去除类型中的引用
template<typename T>
typename remove_reference<T>::type &&move(T &&t)//右值
{
//static_cast就相当于显示地类型转换,百度百科里面是这样
/*
int i;
float f=166.71;
i=static_cast<int>(f);
结果i是166
*/
return static_cast<typename remove_reference<T>::type &&>(t); //都是右值!!
}
void fun2()
{
string s1("hi!"), s2;
s2=std::move(string("bye!")); //ok:从一个右值移动
cout<<"s2=std::move(string(bye!));s2:"<<s2<<endl;
s2=std::move(s1); //执行之后s1有不定值
cout<<"s2=std::move(s1);s2:"<<s2<<"\n"
<<"s2=std::move(s1);s1:"<<s1<<endl;
}
/**************************************
Forwarding
**************************************/
template<typename F, typename T1, typename T2>
void flip1(F f, T1 t1, T2 t2)
{
f(t1, t2);
}
void f(int v1, int &v2) //v2是一个引用
{
cout<<v1<<" "<<++v2<<endl;
}
void fun3()
{
int i,j=1;
f(42, i);
cout<<"f(42, i);i:"<<i<<endl;
flip1(f, j, 42);
cout<<"flip1(f, j, 42);j:"<<j<<endl;
}
/**
Defining Function Parameters That Retain Type Information
*/
template<typename F, typename T1, typename T2>
void flip2(F f, T1 &&t1, T2 &&t2) //两个都是右值引用!!
{
f(t1, t2); //吧t1+1输出。两个右值引用,那么t1和t2的值是变了的
}
void fun4()
{
flip2(f, 8, 8);
cout<<"flip2(f, i, j);j:"<<endl;
}
/**
Using std::forward to Preserve Type Information in a Call
*/
/*
这里forward返回的是一个右值引用,会改变值的大小
*/
template<typename F, typename T1, typename T2>
void flip(F f, T1 &&t1, T2 &&t2)
{
f(std::forward<T1>(t1), std::forward<T2>(t2));
}
void fun5()
{
int j=8;
flip(f, j, j); //这里和上面有点不同了,注意这里第二个j要填左值参数,因为在f里面将第二个j的值改变了
//所以这里虽然传的是形参,但是forward把它还原成右值引用了,还是会改变大小
cout<<"flip(f, i, j);j:"<<j<<endl;
}
int main()
{
cout<<">>------------------------------fun1-----------------------------------<<"<<endl;
fun1();
cout<<">>------------------------------fun2-----------------------------------<<"<<endl;
fun2();
cout<<">>------------------------------fun3-----------------------------------<<"<<endl;
fun3();
cout<<">>------------------------------fun4-----------------------------------<<"<<endl;
fun4();
cout<<">>------------------------------fun5-----------------------------------<<"<<endl;
fun5();
system("pause");
return 0;
}