decltype(auto)类型推导:return x vs. return(x)

时间:2019-04-24 08:47:53

标签: c++ c++14 auto decltype decltype-auto

我正在看isocpp.org FAQ on C++14 language extensions,读到有关decltype(auto)的信息:

  

...

     

注意: decltype(auto)主要用于推导转发函数和类似包装的返回类型,如上所示,在该类型中,您希望类型精确地“跟踪”您所用的某些表达式重新调用。但是,除此以外,decltype(auto)并不打算被广泛使用。特别是,尽管它可以用来声明局部变量,但是这样做可能只是一种反模式,因为局部变量的引用性不应该依赖于初始化表达式。另外,它对如何编写return语句也很敏感。这两个函数具有不同的返回类型:

decltype(auto) look_up_a_string_1() { auto str = lookup1(); return str;  }
decltype(auto) look_up_a_string_2() { auto str = lookup1(); return(str); }
     

第一个返回字符串,第二个返回字符串string &,它是对局部变量str的引用。

我的问题:示例中的返回类型是否应该相反,我的意思是,括号应该形成一个表达式,其类型应该是非引用(或右值引用)?并且没有括号,说str的意思是“对str的左值引用”。我错了吗?

2 个答案:

答案 0 :(得分:6)

是的,括号构成一个表达式。表达式不是引用类型ever

  

如果表达式最初的类型为“对T的引用”([dcl.ref],[dcl.init.ref]),则在进行任何进一步分析之前,将类型调整为T。表达式指定由引用表示的对象或函数,并且表达式取决于表达式是左值还是x值。

“对T的引用”表示左值和右值引用。但是表达式确实具有值类别。 str作为一个表达式是一个左值,(str)也是一个左值,因为括号会保留类型和值类别。

由于在第二种情况下将decltype应用于左值表达式,因此它会生成一个左值引用。

在第一种情况下,id表达式的特殊请求规则将返回“实体类型”,这是一种值类型。

答案 1 :(得分:2)

尽管直觉,FAQ仍是正确的

(@ lubgr指出了另一个问题的relevant answer

语言规范说:

  

如果参数是对象/函数的未括号名称...则decltype指定此表达式指定的实体的声明类型。

     

如果参数是类型T的任何其他表达式,则...   b)如果表达式的值类别是左值,则decltype指定T&   ...   请注意,如果将对象的名称加上括号,则它成为左值表达式,因此decltype(arg)和decltype((arg))通常是不同的类型。

因此,非括号的情况是一种例外/特殊情况,显然是为了方便使用decltype(auto)返回引用而引入的;没有特殊外壳,规则@StoryTeller生效:

  

如果表达式最初的类型为“对T的引用”([dcl.ref],[dcl.init.ref]),则在进行任何进一步分析之前,将类型调整为T。

这将使返回引用变得困难。

绝对具有其他magick定义,例如在索引0处具有0的元组或空字符串的破坏顺序,具有引用的临时生命周期扩展以及其他类似的奇迹...