我正在查看有关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
的左值引用"。我错了吗?
是的,括号形成一个表达式。表达式永远不是引用类型。
如果表达式最初具有类型"引用 T"([dcl.ref], [dcl.init.ref]),则在进行任何进一步分析之前,该类型将调整为 T。表达式指定由引用表示的对象或函数,表达式是左值或 x值,具体取决于表达式。
"对T的引用"是指左值和右值引用。但表达式确实具有值类别。str
作为表达式是左值,(str)
也是如此,因为括号保留类型和值类别。
由于decltype
在第二种情况下应用于左值表达式,因此它会生成左值引用。
在第一种情况下,id-表达式的特殊请求规则返回"实体的类型",这是一种值类型。
常见问题解答是正确的,尽管直觉
(@lubgr指出了另一个问题的相关答案)
语言规范说:
如果参数是对象/函数的无括号名称...然后,Decltype 指定此表达式指定的实体的声明类型。
如果参数是 T 类型的任何其他表达式,则... b) 如果表达式的值类别是左值,则 decltype 指定 T& ... 请注意,如果对象的名称被括起来,它就会变成一个左值表达式,因此 decltype(arg) 和 decltype((arg)) 通常是不同的类型。
因此,非括号大小写是一个例外/特殊情况,显然是为了方便使用 decltype(auto) 返回引用而引入的;如果没有特殊大小写,引号@StoryTeller规则是有效的:
如果表达式最初具有类型"引用 T"([dcl.ref], [dcl.init.ref]),则在进行任何进一步分析之前,该类型将调整为 T。
这将使返回引用变得困难。
绝对与其他魔法定义并列,例如元组的破坏顺序或在索引 0 处为 0 的空字符串、带有引用的临时寿命延长和其他类似的奇迹......