decltype 行为背后的基本原理是什么?

What is the rationale behind decltype behavior?

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

int x;
decltype(x) y = x;

等同于 int y = x; 但是,

int x;
decltype((x)) y = x;

等同于int& y = x;.

分别

 decltype(auto) f1()
 {
   int x = 0;
   return x; // decltype(x) is int, so f1 returns int
 }

但是

 decltype(auto) f2()
 {
   int x = 0;
   return (x); // decltype((x)) is int&, so f2 returns int&
 }

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

后记:

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

需要区分实体和表达式。

考虑以下问题:

How long is Mississippi?

这个问题有两个答案:

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

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

他们想要一种获取标识符声明类型的方法。

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

decltype(x)给出标识符x的声明类型。如果您传递 decltype 不是标识符的内容,它会确定类型,然后为左值附加 &,为 xvalue 附加 &&,为纯右值附加任何内容。

概念上你可以认为它是变量类型和表达式类型的区别。但这并不是标准描述的方式。

他们本可以使用两个不同的关键字来表示这两件事。他们没有。

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

It’s been a while, but here’s what I (think I) remember:

Two separate keywords for differentiating these two kinds of semantics was never considered. (Introducing new keywords is not done lightly).

As to the change of the semantics of decltype((x)), discussion in the core working group converged to treating (x) as an expression, rather than an identifier, which perhaps is more “internally consistent” with the language rules.

People were aware that this could potentially be confusing in some cases, but the consensus (while perhaps not everyone’s preference) was eventually to be consistent with the standard’s prior definition of what is an identifier and what is an expression.

The example you link to [this question's example] is indeed surprising. At the time, deducing a function’s return type from its return expression using decltype(auto) was not yet part of the language, so I don’t think this particular use case was on anyone’s radar.