b1s*_*sub 11 c++ templates language-lawyer perfect-forwarding
请考虑C++模板中的引用:完整指南(第2版):
Run Code Online (Sandbox Code Playgroud)decltype(auto) ret{std::invoke(std::forward<Callable>(op), std::forward<Args>(args)...)}; ... return ret;需要注意的是,宣布
ret与auto&&不正确.作为引用,auto&&将返回值的生存期延长到其作用域的末尾,但不超出return对函数调用者的语句.
作者说这auto&&不适合完美转发回报值.但是,是否也没有decltype(auto)形成对xvalue/lvalue的引用?国际海事组织,decltype(auto)然后遭受同样的问题.那么,作者有什么意义呢?
编辑:
上面的代码片段应该放在这个函数模板中.
template<typename Callable, typename... Args>
decltype(auto) call(Callable&& op, Args&&... args) {
// here
}
Run Code Online (Sandbox Code Playgroud)
这里有两个推论.一个来自返回表达式,一个来自std::invoke表达式.因为decltype(auto)推断为未表示的id-expression的声明类型,我们可以专注于从std::invoke表达式中推导出来.
如果占位符是
decltype(auto)类型说明符,T则应仅为占位符.推导出的类型T是按照[dcl.type.simple]中的描述确定的,好像e它是操作数一样decltype.
对于表达式
e,表示的类型decltype(e)定义如下:
if
e是一个未加括号的id-expression,命名一个结构化绑定([dcl.struct.bind]),decltype(e)是结构化绑定声明规范中给出的引用类型;否则,如果
e是未加密码的id-expression或未加括号的类成员访问,decltype(e)则是名为的实体的类型e.如果没有这样的实体,或者e命名一组重载函数,程序就会形成错误;否则,如果
e是xvalue,decltype(e)则是T&&,其中T的类型是e;否则,如果
e是左值,decltype(e)则是T&,其中T的类型e;否则,
decltype(e)是的类型e.
注释decltype(e)推断为T而不是T&&if e是prvalue.这与之不同auto&&.
因此,如果std::invoke(std::forward<Callable>(op), std::forward<Args>(args)...)是prvalue,例如,返回类型Callable不是引用,即按值返回,ret则推断为相同类型而不是引用,这完美地转发了按值返回的语义.