C++ decltype 和括号 - 为什么?

Ofe*_*lon 31 c++ decltype language-lawyer c++11

该主题之前讨论 ,但这不是重复的。

当有人问decltype(a)及 和之间的区别时decltype((a)),通常的回答是 -a是一个变量,(a)是一个表达式。我觉得这个答案并不令人满意。

首先,a也是一个表达式。主要表达式的选项包括 -

  • ( 表达 )
  • id 表达式

更重要的是, decltype 的措辞非常非常明确地考虑了括号

For an expression e, the type denoted by decltype(e) is defined as follows:
(1.1)  if e is an unparenthesized id-expression naming a structured binding, ...
(1.2)  otherwise, if e is an unparenthesized id-expression naming a non-type template-parameter, ...
(1.3)  otherwise, if e is an unparenthesized id-expression or an unparenthesized class member access, ...
(1.4)  otherwise, ...
Run Code Online (Sandbox Code Playgroud)

所以问题仍然存在。为什么括号的处理方式不同?是否有人熟悉其背后的技术论文或委员会讨论?对括号的明确考虑导致认为这不是疏忽,所以一定有我遗漏的技术原因。

小智 18

这不是疏忽。有趣的是,在Decltype 和 auto (revision 4) (N1705=04-0145) 中有一个声明:

decltype 规则现在明确指出decltype((e)) == decltype(e)(如 EWG 建议的那样)。

但是在Decltype(修订版 6)中:提议的措辞(N2115=06-018)的变化之一是

decltype 中的括号表达式不被视为id-expression.

措辞没有依据,但我认为这是 decltype 的一种扩展,使用了一些不同的语法,换句话说,它旨在区分这些情况。

C++draft9.2.8.4 中显示了它的用法:

const int&& foo();
int i;
struct A { double x; };
const A* a = new A();
decltype(foo()) x1 = 17;        // type is const int&&
decltype(i) x2;                 // type is int
decltype(a->x) x3;              // type is double
decltype((a->x)) x4 = x3;       // type is const double&
Run Code Online (Sandbox Code Playgroud)

真正有趣的是它如何处理return语句:

decltype(auto) f()
{
    int i{ 0 };
    return (i);
}
Run Code Online (Sandbox Code Playgroud)

我的 Visual Studio 2019 建议我删除多余的括号,但实际上它们变成了decltype((i))哪些更改返回值,int&因为返回对局部变量的引用,因此它成为 UB。


Sto*_*ica 14

为什么括号的处理方式不同?

括号没有区别对待。未加括号的 id 表达式被区别对待。

当存在括号时,所有表达式的常规规则适用。类型和值类别被提取并编码在 的类型中decltype

有特殊规定,以便我们可以更轻松地编写有用的代码。当应用于decltype(成员)变量的名称时,我们通常不想要某种类型来表示将变量视为表达式时的属性。相反,我们只需要声明变量的类型,而不必应用大量类型特征来获取它。这正是我们decltype指定的内容。

如果我们确实关心变量作为表达式的属性,那么我们仍然可以通过一对额外的括号轻松获得它。

  • @OfekShilon - 他们的类型不是参考。[表达式的类型永远不会作为参考进行分析](https://eel.is/c++draft/expr#type-1.sentence-1)。但 dectlype 只能解析为类型,它不仅可以告诉我们表达式的类型,还可以告诉我们它的值类别。值类别由引用类型“编码”。左值是“&”,x值是“&&”,纯右值不是引用类型。 (2认同)