我正在编写一个库,它将来自其他库的许多函数和方法进行包装。为了避免复制返回值,我使用std::forward
进行应用,如下所示:
template<class T>
T&& wrapper(T&& t) {
f(t); // t passed as lvalue
return std::forward<T>(t);
}
f
返回void
并使用T&&
(或以值为重载)。包装器始终返回包装器的参数,并且在返回值上应保留参数的值。在return
中实际上需要使用std::forward
吗?RVO是否使其变得多余?事实上,它是一个引用(R或L)是否使其变得多余?如果返回不是最后一个函数语句(在某些if内部),是否需要?
是否应该将wrapper()
返回void
或T&&
存在争议,因为调用者可以通过参数(引用,R或L)访问评估的值。但在我的情况下,我需要返回值,以便可以在表达式中使用wrapper()
。
这可能与问题无关,但已知函数f
不从t
中窃取,因此f(std::forward<T>(t))
中第一次使用std::forward
是多余的,我已将其删除。
我编写了一个小测试:https://gist.github.com/3910503
测试显示,在gcc48和clang32中使用-O3未转发的T
会创建额外的副本(RVO不会启动)。
此外,我无法从UB中获得不良行为:
auto&& tmp = wrapper(42);
这并不能证明任何事情,因为它是未定义的行为(如果确实是UB的话)。
&&
叫做“通用引用”,我就... - Nicol Bolas