使用auto &&完美转发返回值

b1s*_*sub 11 c++ templates language-lawyer perfect-forwarding

请考虑C++模板中的引用:完整指南(第2版):

decltype(auto) ret{std::invoke(std::forward<Callable>(op),
                               std::forward<Args>(args)...)};
...
return ret;
Run Code Online (Sandbox Code Playgroud)

需要注意的是,宣布retauto&&不正确.作为引用,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)

Lig*_*ica 5

但是,decltype(auto) 不也形成对 xvalue/lvalue 的引用吗?

不。

部分decltype(auto)神奇之处在于它知道ret是一个左值,所以它不会形成引用

如果您写了return (ret),它确实会解析为引用类型,并且您将返回对局部变量的引用。

tl;dr:decltype(auto)并不总是与auto&&.

  • @b1sub 你忘记了 [\[dcl.type.simple\]/4.2](http://eel.is/c++draft/dcl.type.simple#4.2) 这在这里是相关的 (4认同)

xsk*_*xzr 5

这里有两个推论.一个来自返回表达式,一个来自std::invoke表达式.因为decltype(auto)推断为未表示的id-expression的声明类型,我们可以专注于从std::invoke表达式中推导出来.

引自[dcl.type.auto.deduct]第5段:

如果占位符是decltype(auto) 类型说明符,T则应仅为占位符.推导出的类型T是按照[dcl.type.simple]中的描述确定的,好像e它是操作数一样decltype.

引自[dcl.type.simple]第4段:

对于表达式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则推断为相同类型而不是引用,这完美地转发了按值返回的语义.