CPP——转发

       1. 某些函数需要将其一个或多个实参连同类型不变地转发给其他函数。在此情况下,我们需要保持被转发实参的所有性质。包括实参类型是否const的,以及实参是左值还是右值。
       2. 例子

template <typename F, typename T1, typename T2>
void flip1(F f, T1 t1, T2 t2) //f是可调用对象
{
    f(t2, t1); //将两个额外的参数逆序传递给f
}

        ○ 这个函数一般情况下工作得很好,但当我们希望用它调用一个接受引用参数的函数就会出现问题:

void f(int v1, int &v2)
{
    cout << v1 << " " << ++v2 << endl;
}


        ○ f改变了绑定到v2的实参的值。但是,如果通过flip1调用f,f所做的改变就不会影响实参:

f(42, i); //f改变了实参i
flip1(f, j, 42); //==>f(42,j); 通过flip1调用f不会改变j


        ○ 问题在于j被传递给flip1的参数t1.此参数是一个普通的丶非引用的类型int,而非int&.因此,这个flip1调用会实例化为

void flip1(void(*fcn)(int, int&), int t1, int t2);


        ○ 因此j的值被拷贝到t1中。f中的引用参数被绑定到t1,而非j,从而其改变不会影响j。
        ○ 正确的定义:

template<typename F, typename T1, typename T2>
void flip2(F f, T1 &&t1, T2 &&t2)
{
    f(t2, t1);
}


        ○ 如果调用flip2(f, j, 42),将传递给参数t1一个左值j,而T1被推断为int&(左传右的第一个例外规则),此时t1类型为(int& &&),因此T1被折叠为int&;从而t1被绑定到j上,v2也因此被被绑定到t1,即被绑定到j。关于引用折叠
 

如果一个函数参数是指向模板类型参数的右值引用(如T&&),它对应的实参的const属性和左值/右值属性将得到保持
 

        ○ 但是flip2对于接受一个左值引用的函数工作得很好,而不能用于接受右值引用参数的函数,如

void g(int &&i, int &j)
{
    cout << i << " " << j << endl;
}


        ○ 当试图通过flip2调用g,则参数t2将被传递给g的右值引用参数。即使我们传递一个右值给flip2:

flip2(g, i, 42); //错误:不能将一个左值实例化int&&


        ○ 因为此时filp2实例化为

flip2<void (*)(int &&, int &), int &, int>;

所以调用g时发生错误。
    3. 保持类型信息:std::forward
        ○ 这个新标准库设施可以保持原始实参的类型。不同于move,forward必须通过显式模板实参来调用。forward返回该显式实参类型的右值引用。
        ○ 通常,我们使用forward传递那些定义为模板类型参数的右值引用的函数参数。通过其返回类型上的引用折叠,forward可以保持给定实参的左值/右值属性。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weisonx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值