4

我正在查看有关 C++14 语言扩展的 isocpp.org 常见问题解答,阅读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”。我错了吗?

4

2 回答 2

6

是的,括号形成一个表达式。表达式永远不是引用类型。

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

“对 T 的引用”意味着左值和右值引用。但是表达式确实有一个值类别。str因为表达式是左值,所以(str)括号保留类型和值类别。

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

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

于 2019-04-24T08:53:13.903 回答
2

常见问题解答是正确的,尽管有直觉

(@lubgr 指出了另一个问题的相关答案)

语言规范说:

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

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

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

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

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

绝对与其他魔术定义一起排名在那里,例如元组的破坏顺序或索引 0 处为 0 的空字符串,带有引用的临时生命周期延长和其他类似的奇迹......

于 2019-04-24T08:59:12.067 回答