C++11 为什么 'decltype(x)' 和 'decltype((x))' 的类型不同?
C++11 why the type of 'decltype(x)' and 'decltype((x))' are different?
我发现它们是不同的,语言标准规定了每个语句应该检索什么样的类型(变量和表达式之间的区别)。但我真的很想知道为什么这两种类型应该不同?
#include<stdio.h>
int x=0;
decltype((x)) y=x;
int main()
{
y=2;
printf("%d,",x);
decltype((1+2))&z=x;//OK (1+2) is an express, but why decltype should differ?
z=3;
printf("%d\n",x);
return 0;
}
运行 结果是'2,3'
那么为什么decltype((int))
被设计成int&
,这里C++语言设计的考虑是什么?任何需要这样设计的语法一致性? (我不想得到“这是设计使然”)
感谢您的解释。
如果您阅读例如this decltype
reference你会看到
2) If the argument is an unparenthesized id-expression or an unparenthesized class member access expression, ...
3) If the argument is any other expression...
...
b) if the value category of expression is lvalue, then decltype
yields T&
;
[强调我的]
然后再往下一点注释
Note that if the name of an object is parenthesized, it is treated as an ordinary lvalue expression, thus decltype(x)
and decltype((x))
are often different types.
因为您使用带括号的表达式,所以它被视为左值,这意味着上面的 3.b 是活动的,如果 x
是 [=,decltype((x))
给您 int&
19=].
需要注意的是,虽然参考不是权威的,但它是从规范中派生出来的,通常是可靠和正确的。
来自 C++11 规范 ISO/IEC 14882:2011,第 7.1.6.2 节 [dcl.type.simple],sub-section 4:
The type denoted by decltype(e)
is defined as follows:
— if e
is an unparenthesized id-expression or an unparenthesized class member access (5.2.5), decltype(e)
is the type of the entity named by e
. If there is no such entity, or if e
names a set of overloaded functions, the program is ill-formed;
— otherwise, if e
is an xvalue, decltype(e)
is T&&
, where T
is the type of e
;
— otherwise, if e
is an lvalue, decltype(e)
is T&
, where T
is the type of e
;
— otherwise, decltype(e)
is the type of e
举个例子:
struct A { double x; };
const A* a = new A();
...
decltype((a->x)) x4 = x3; // type is const double&
基本上与之前链接的参考文献所说的完全相同。
对于您的示例,规范中的 e
是 (x)
(因为您有 declspec((x))
)。现在第一种情况不适合,因为 (x)
不是未加括号的表达式。第二种情况不适合,因为 (x)
不是 xvalue。尽管第三种情况匹配,(x)
是类型 int
的左值,导致 decltype((x))
成为 int&
.
所以您查询的答案很简单:因为规范是这样说的。
好吧,我在这里看到的答案是 "the specification says so"。我查看了 stroustrup 的原始 decltype 草稿,这就是它所说的。
if expr in decltype(expr) is a variable or formal parameter the
programmer can trace down the variable’s or parameter’s declaration,
and the result of decltype is exactly the declared type. If expr is a
function invocation, the programmer can perform manual overload
resolution; the result of the decltype is the return type in the
prototype of the best matching function. The prototypes of the
built-in operators are defined by the standard, and if some are
missing, the rule that an lvalue has a reference type applies.
看看这里的最后一句话,我想这就解释了。由于括号是built-in运算符来表示和表达。
我发现它们是不同的,语言标准规定了每个语句应该检索什么样的类型(变量和表达式之间的区别)。但我真的很想知道为什么这两种类型应该不同?
#include<stdio.h>
int x=0;
decltype((x)) y=x;
int main()
{
y=2;
printf("%d,",x);
decltype((1+2))&z=x;//OK (1+2) is an express, but why decltype should differ?
z=3;
printf("%d\n",x);
return 0;
}
运行 结果是'2,3'
那么为什么decltype((int))
被设计成int&
,这里C++语言设计的考虑是什么?任何需要这样设计的语法一致性? (我不想得到“这是设计使然”)
感谢您的解释。
如果您阅读例如this decltype
reference你会看到
2) If the argument is an unparenthesized id-expression or an unparenthesized class member access expression, ...
3) If the argument is any other expression...
... b) if the value category of expression is lvalue, then
decltype
yieldsT&
;
[强调我的]
然后再往下一点注释
Note that if the name of an object is parenthesized, it is treated as an ordinary lvalue expression, thus
decltype(x)
anddecltype((x))
are often different types.
因为您使用带括号的表达式,所以它被视为左值,这意味着上面的 3.b 是活动的,如果 x
是 [=,decltype((x))
给您 int&
19=].
需要注意的是,虽然参考不是权威的,但它是从规范中派生出来的,通常是可靠和正确的。
来自 C++11 规范 ISO/IEC 14882:2011,第 7.1.6.2 节 [dcl.type.simple],sub-section 4:
The type denoted by
decltype(e)
is defined as follows:— if
e
is an unparenthesized id-expression or an unparenthesized class member access (5.2.5),decltype(e)
is the type of the entity named bye
. If there is no such entity, or ife
names a set of overloaded functions, the program is ill-formed;— otherwise, if
e
is an xvalue,decltype(e)
isT&&
, whereT
is the type ofe
;— otherwise, if
e
is an lvalue,decltype(e)
isT&
, whereT
is the type ofe
;— otherwise,
decltype(e)
is the type ofe
举个例子:
struct A { double x; }; const A* a = new A(); ... decltype((a->x)) x4 = x3; // type is const double&
基本上与之前链接的参考文献所说的完全相同。
对于您的示例,规范中的 e
是 (x)
(因为您有 declspec((x))
)。现在第一种情况不适合,因为 (x)
不是未加括号的表达式。第二种情况不适合,因为 (x)
不是 xvalue。尽管第三种情况匹配,(x)
是类型 int
的左值,导致 decltype((x))
成为 int&
.
所以您查询的答案很简单:因为规范是这样说的。
好吧,我在这里看到的答案是 "the specification says so"。我查看了 stroustrup 的原始 decltype 草稿,这就是它所说的。
if expr in decltype(expr) is a variable or formal parameter the programmer can trace down the variable’s or parameter’s declaration, and the result of decltype is exactly the declared type. If expr is a function invocation, the programmer can perform manual overload resolution; the result of the decltype is the return type in the prototype of the best matching function. The prototypes of the built-in operators are defined by the standard, and if some are missing, the rule that an lvalue has a reference type applies.
看看这里的最后一句话,我想这就解释了。由于括号是built-in运算符来表示和表达。