【问题标题】:decltype(auto) type deduction: return x vs. return (x)decltype(auto) 类型推导:return x vs. return (x)
【发布时间】:2019-04-24 08:47:52
【问题描述】:

我在看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 的左值引用”。我错了吗?

【问题讨论】:

  • 反过来应该是什么?建议还是返回类型?
  • This answer 似乎相关。
  • @StoryTeller:见编辑。
  • 简而言之:返回类型分别为decltype(str)decltype((str))。第一个触发了decltype的操作数是变量的裸名的特殊情况,并且规则不同(它完全模仿变量的类型)。

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


【解决方案1】:

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

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

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

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

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

【讨论】:

  • 你确定你的第一句话是这样吗?如果是这样,我们怎么能使用引用类型作为函数参数?
  • @einpoklum - 非常确定。如果a 是对某事物的引用,那么a 是一个左值表达式,用于指定该事物。因此,引用参数可以绑定到被指定的事物。关于如何从其他表达式初始化引用有适当的措辞。
【解决方案2】:

FAQ 是正确的,尽管直觉

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

语言规范说:

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

如果参数是 T 类型的任何其他表达式,那么 ... b) 如果表达式的值类别是左值,则decltype指定T& ... 请注意,如果一个对象的名称被括号括起来,它就变成了一个左值表达式,因此 decltype(arg) 和 decltype((arg)) 通常是不同的类型。

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

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

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

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

【讨论】:

  • 如果你问我,这里真的没有什么奇怪或新的东西。自从 decltype 说明符最初在 C++11 中引入 [dcl.type.simple]/4...decltype(auto) 以来,就一直存在不带括号的 id-expressions 的例外情况,它只是遵循现有的 decltype 类型推导规则,即整点……
猜你喜欢
  • 1970-01-01
  • 2017-12-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多