万能引用,完美转发,std::forward

引出万能引用:

#include 
#include 
using namespace std;
void add(int i, int &j) //j是一个引用
{
    j++;
    std::cout << j << std::endl;
}

template<typename f,typename T,typename U>
void forward(f callback, T i, U j)//我们希望通过这个函数模板,把给进来的实参的所有属性传递给callback
{
    callback(i, j);
}
int main()
{
    int a = 10;
    std::cout << a << std::endl; //10

    //我们本意是通过这个函数模板,把a的值变成11,但是函数执行了以后,a还是10,
    //原因是U被推断成了int类型了而不是int&。
    forward(add, 1, a);//11
    std::cout << a << std::endl;//10

    return 0;
}

万能引用,完美转发,std::forward_第1张图片
我们改造一下,希望通过万能引用解决以上带来的问题。

#include 
#include 
#include 
#include 
using namespace std;
void add(int i, int &j) //j是一个引用
{
    j++;
    std::cout << j << std::endl;
}
template<typename f,typename T,typename U>
void forward(f callback, T &&i, U &&j)//改成了万能引用,和右值引用非常像,只不过,存在的语意不一样
{
    callback(i, j);
}
int main()
{
    int a = 10;
    std::cout << a << std::endl; //10
    forward(add, 1, a);//11
    //1是右值,即&& ,而i是&& 两个&& &&结合,所以T是&&,
    //a是左值,即&,而j是&&,& &&结合,所以U是&,,有&即为左值
    std::cout << a << std::endl;//11
    return 0;
}

在这里插入图片描述
但是以上的例子还有存在的问题,如下

#include 
#include 
#include 
#include 
using namespace std;
void add(int &&i, int &j) //把i改为&&
{
    j++;
    std::cout << j << std::endl;
}
template<typename f,typename T,typename U>
void forward(f callback, T &&i, U &&j)//改成了万能引用,和右值引用非常像,只不过,存在的语意不一样
{
    callback(i, j);
}
int main()
{
    int a = 10;
    std::cout << a << std::endl; //10
    forward(add, 1, a);//11
    //1是右值,即&& ,而i是&& 两个&& &&结合,所以T是&&,
    //a是左值,即&,而j是&&,& &&结合,所以U是&,,有&即为左值
    std::cout << a << std::endl;//11
    return 0;
}

万能引用,完美转发,std::forward_第2张图片
把i改为&&,编译错误,因为是函数模板当中的i本身是一个左值,把一个左值传递给add函数当中的右值引用,当然编译错误,所以我们引出了std::forward.

#include 
#include 
#include 
#include 
using namespace std;

void add(int &&i, int &j) //把i改为&&
{
    j++;
    std::cout << j << std::endl;
}

template<typename f,typename T,typename U>
void forward(f callback, T &&i, U &&j)//改成了万能引用,和右值引用非常像,只不过,存在的语意不一样
{
    callback(
        std::forward<T>(i),//把给进来的实参类型不变的传递给add函数的形参i
        std::forward<U>(j)
    );
}
int main()
{
    int a = 10;
    std::cout << a << std::endl; //10
    forward(add, 1, a);//11
    //1是右值,即&& ,而i是&& 两个&& &&结合,所以T是&&,
    //a是左值,即&,而j是&&,& &&结合,所以U是&,,有&即为左值
    std::cout << a << std::endl;//11
    return 0;
}

顺利通过编译。

你可能感兴趣的:(#,c++,template,c++,visual,studio,cocos2d)