首页 > 代码库 > 【足迹C++primer】59、模板左值右值的转换

【足迹C++primer】59、模板左值右值的转换

模板左值右值的转换


/**
* 功能:模板左值右值的转换
* 时间: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;
}