1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > C++ Primer 5th笔记(chap 16 模板和泛型编程)转发

C++ Primer 5th笔记(chap 16 模板和泛型编程)转发

时间:2018-09-07 06:29:55

相关推荐

C++ Primer 5th笔记(chap 16 模板和泛型编程)转发

1. 转发

某些函数需要将其一个或多个实参连同类型不变地转发给其他函数。 因此需要保持被转发实参的所有性质, 包括实参类型是否是 const 的以及实参是左值还是右值。

//接受一个可调用对象和另外两个参数的模板// 对 “翻转” 的参数调用给定的可调用对象// flipl 是一个不完整的实现: 顶层 const 和引用丢失了template <typename F, typename T1, typename T2> void flipl (F f , T1 tl, T2 t2){f (t2, t1);}

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

void f (int v1, int &v2) // 注意 v2 是一个引用{cout « v1 « "" << ++v2 « endl;}//f 改变了绑定到 v2 的实参的值。 但是, 如果我们通过 flipl 调用 f, f所做的改变就不会影响实参:f(42, j); // f 改变了实参iflipl (f, j, 42); // 通过 flipl 调用 f 不会改变 j//等价于void flipl (void(*fcn) (int, int & ), int t1, int t2);

1.1 定义能保持类型信息的函数参数

通过翻转函数传递一个引用, 使其参数能保持给定实参的“ 左值性”。保持参数的 const 属性。

将一个函数参数定义为一个指向模板类型参数的右值引用 -> 保持其对应实参的所有类型信息。

使用引用参数( 无论是左值还是右值) -> 保持 const属性

eg. 在引用类型中的 const 是底层的。 如果我们将函数参数定义为 T1&&和 T2 &&, 通过引用折叠可以保持翻转实参的左值/右值属性

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

flip2解决了一半问题。 它对于接受一个左值引用的函数工作得很好,但不能用于接受右值引用参数的函数。 例如:

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

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

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

2. 接受右值引用参数的模板函数

template <typename T> void f 3 (T && val){T t = val; // 拷贝还是绑定一个引用?t = fcn(t); //赋值只改变t还是既改变t又改变val?if (val == t) {/* ... */ } //若T是引用类型,则一直为true}

右值引用通常用于两种情况:

模板转发其实参模板被重载

template <typename T> void f (T &&) ;//绑定到非const右值template <typename T> void f (const T &);//左值和const右值

3. std::forward

forward 传递 flip2 的参数,能保持原始实参的类型。

必须通过显式模板实参来调用forward 返回该显式实参类型的右值引用。 即, forward的返回类型是 T &&。

通常情况下, 我们使用 forward 传递那些定义为模板类型参数的右值引用的函数参数。 通过其返回类型上的引用折叠, forward 可以保持给定实参的左值/右值属性:

template <typename Type〉 intermediary (Type && arg){finalFcn (std::forward<Type>(arg));…}

使用 Type 作为 forward 的显式模板实参类型, 它是从 arg 推断出来的。 由于arg 是一个模板类型参数的右值引用, Type 将表示传递给 arg的实参的所有类型信息。

如果实参是一个右值, 则 Type 是一个普通( 非引用) 类型, forward将返回Type&&如果实参是一个左值, 则通过引用折叠, Type 本身是一个左值引用类型。 在此情况下, 返冋类型是一个指向左值引用类型的右值引用。 再次对 forward的返回类型进行引用折叠, 将返回一个左值引用类型。

使用 forward, 我们可以再次重写翻转函数:

template <typename F, typename T1, typename T2> void flip (F f, T1 &&t1, T2 &&t2){f(std::forward<T2> (t2), std::forward<T1> (t1));}

如果我们调用 flip (g, i, 42 ) , i 将以 int &类型传递给 g, 42 将以 int &&类型传递给 g.

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。