
F.19: For "forward" parameters, pass by TP&& and only std::forward the parameter(对于只传递不处理的参数,使用模板类型TP&&并在传递时使用std::forward)
Reason(原因)
If the object is to be passed onward to other code and not directly used by this function, we want to make this function agnostic to the argument const-ness and rvalue-ness.
如果对象不在本函数内部使用而是继续传递给其他代码,我们希望本函数不会改变参数的常数特性和右值特性。
译者注:
考虑下面的函数(代码来自《C++程序设计语言》):
string f(string&& s){ if(s.size()) s[0]=toupper(s[0]); return s;}
右值引用作为参数类型使用的时候,首先被实参初始化,其结果是实参将无效化(右值引用的定义)。在函数内部,由于s已经夺取了实参的内容,因此可以作为左值自由使用。但是如果不是在函数体中直接使用而希望作为右值继续传递给另外一个函数,就不能直接使用s作为实参(因为它已经变成了左值引用),而是使用forward恢复它的右值特性。
关于forward和右值引用的用法可以参照作者以下文章:
https://mp.weixin.qq.com/s/RJb7PhPA1xoDEIwJRNxrCg
In that case, and only that case, make the parameter TP&& where TP is a template type parameter -- it both ignores and preserves const-ness and rvalue-ness. Therefore any code that uses a TP&& is implicitly declaring that it itself doesn't care about the variable's const-ness and rvalue-ness (because it is ignored), but that intends to pass the value onward to other code that does care about const-ness and rvalue-ness (because it is preserved). When used as a parameter TP&& is safe because any temporary objects passed from the caller will live for the duration of the function call. A parameter of type TP&& should essentially always be passed onward via std::forward in the body of the function.
在这种情况下,也只有在这种(右值引用参数只传递不使用)情况下,将TP参数定义为TP&&(这里TP是模板类型)--这样可以无视并维持常量特性和右值特性。因此任何使用TP&&的代码声明了它不在乎变量的常量特性和右值特性(因为已经被忽略),但会将该值(不加改变地)继续传递给其他不在乎常量特性和右值特性的代码(因为这些特性会被维持)。因为任何从调用者传来的临时对象都会在函数调用期间保持有效性(原因是调用者只有在函数调用之后才有机会销毁这个对象),因此当TP&&被作为参数(在函数内部)使用时是安全的。TP&&类型的参数本质上总是应该在函数体中通过std::forward继续传递的。
译者注:最终还是要被某段代码作为左值使用的。
Example
template inline auto invoke(F f, Args&&... args) { return f(forward(args)...); }
??? calls ???
Enforcement(建议)
- Flag a function that takes a TP&& parameter (where TP is a template type parameter name) and does anything with it other than std::forwarding it exactly once on every static path.在下面情况下发出警示:对于函数使用TP&&类型参数(这里TP是模板类型参数名),除了在所有静态路径上精确地执行一次std::forward操作以外执行了任何(针对改参数的)其他处理。
觉得本文有帮助?请分享给更多人。
更多更新文章,欢迎关注微信公众号【面向对象思考】
面向对象设计,面向对象编程,面向对象思考!