decltype行为背后的理由是什么?

bob*_*eff 57 c++ decltype c++11 type-deduction c++14

正如我在C++ 11 decltype(expression)中所理解的,用于推断给定表达式的完全相同类型.但是当表达式放入括号本身时,则推导类型是对表达式类型的左值引用.例如:

int x;
decltype(x) y = x;
Run Code Online (Sandbox Code Playgroud)

相当于int y = x;但是,

int x;
decltype((x)) y = x;
Run Code Online (Sandbox Code Playgroud)

相当于int& y = x;.

分别

 decltype(auto) f1()
 {
   int x = 0;
   return x; // decltype(x) is int, so f1 returns int
 }
Run Code Online (Sandbox Code Playgroud)

 decltype(auto) f2()
 {
   int x = 0;
   return (x); // decltype((x)) is int&, so f2 returns int&
 }
Run Code Online (Sandbox Code Playgroud)

标准委员会选择这种行为的理由是什么?

后记:

现在我观察到,至少在GCC 6.2实现的情况下,当括号中的表达式更复杂时,例如decltype((x + x))推导的类型是T,但不是T&.这更令人困惑.我不知道这种行为是否标准.

Yak*_*ont 35

他们想要一种方法来获得标识符的声明类型.

他们还想要一种方法来获取表达式的类型,包括它是否是临时的信息.

decltype(x)给出标识符的声明类型x.如果传递的decltype内容不是标识符,则确定类型,然后&为lvalues 附加&&xvalues,为prvalues 附加任何内容.

从概念上讲,您可以将其视为变量类型与表达式类型之间的差异.但这并不是标准如何描述它.

他们可以用两个不同的关键词来表示这两件事.他们没有.

  • @bobeff因为`x + 1`是prvalue? (8认同)
  • @bobeff注意``decltype(x + 1)`总是与`decltype((x + 1))`相同``无论```的类型是什么,以及`运算符+'如何为它重载.原因是`x + 1`是一个表达式,因此在它周围添加括号不会改变任何东西. (4认同)

Leo*_*eon 24

需要区分实体和表达.

考虑以下问题:

密西西比河有多长?

这个问题有两个答案:

  1. 密西西比河长2,320英里.
  2. 密西西比州长11个字母.

类似地,当您询问类型x,并且x是标识符时,不清楚您是指用于声明该标识符的类型(即与名称关联的类型x),还是由单一组成的表达式的类型提到那个标识符.事实上,可能有两个不同的关键字(例如entity_typeexpr_type)而不是单个重载decltype.出于某种原因,委员会decltype为这两种不同的用途选择了超载.


Col*_*mbo 18

来自decltype提案的作者之一J. Jarvi:

已经有一段时间了,但这就是我(我想)记得的:

从未考虑过用于区分这两种语义的两个单独的关键字.(引入新关键字不是轻易做到的).

至于语义的变化,decltype((x))核心工作组的讨论融合(x)为一种表达,而不是一种标识符,它可能与语言规则更"内部一致".

人们意识到这在某些情况下可能会令人困惑,但是共识(尽管可能不是每个人的偏好)最终都与标准的先前定义一致,即什么是标识符,什么是表达式.

你链接到[这个问题的例子]的例子确实令人惊讶.当时,使用返回表达式推断函数的返回类型decltype(auto) 还不是语言的一部分,所以我不认为这个特定的用例是在任何人的雷达上.