左值的 decltype 括号语法
decltype parenthesis syntax for a lvalue
我试图更好地理解 decltype 以确定编译时表达式的类型。比方说我用一个双变量来做:
#include <iostream>
#include <type_traits>
int main(){
double a;
typedef decltype(a) a_type;
typedef decltype((a)) ref_a_type;
typedef decltype(a)& o_ref_a_type;
a_type b;
ref_a_type c = b;
o_ref_a_type d = b;
if (std::is_same<decltype(b), double>::value) std::cout << "b is double\n";
if (std::is_same<decltype(c), double&>::value) std::cout << "c is double&\n";
if (std::is_same<decltype(d), double&>::value) std::cout << "d is double&\n";
}
如果我没有理解错的话,这些观点应该是正确的:
decltype(a)
returns double&
如果 a
是左值,否则 double
。
- decltype 推导表达式的类型,除非它应用于变量,在这种情况下它推导该变量的类型。
- 如果变量被括号括起来,它就成为一个左值表达式。
因此,decltype((a))
和 decltype(a)&
在这种情况下是等价的,但并不总是等价的,例如,如果 a
不是变量:
typedef decltype((5)) ref_a_type;
typedef decltype(5)& o_ref_a_type;
则两种类型不等价(ref_a_type
是 int
而 o_ref_a_type
是 int&
,因为在这种情况下额外的括号是无用的)。有人可以对此做出更好的解释吗?我应该使用第一种还是第二种方式?
在我看来,第二种方式比第一种方式更具可读性和可理解性。
就 C++ 标准而言,decltype(e)
的规则非常清楚,所以我将复制它们(来自 [dcl.type.simple]):
For an expression e
, the type denoted by decltype(e)
is defined as follows:
(4.1) — 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;
(4.2) — otherwise, if e
is an xvalue, decltype(e)
is T&&
, where T
is the type of e
;
(4.3) — otherwise, if e
is an lvalue, decltype(e)
is T&
, where T
is the type of e;
(4.4) — otherwise, decltype(e)
is the type of e
.
因此请按顺序查看您的示例:
decltype(a)
: a
是一个未加括号的 id-expression, 所以这只是 a
的类型: double
.
decltype((a))
:现在有括号,所以我们跳过第一个项目符号。 a
不是一个 xvalue,它是一个 lvalue,所以这是 double&
。
decltype(a)&
:又是第一种情况,所以是double&
。
decltype((5))
:这既不是 id-expression(带括号或其他)、xvalue 或 lvalue - 它是 prvalue,所以我们转到获取表达式类型的最后一个项目符号:int
.
decltype(5)&
:与最后一点相同,只是现在您明确添加了一个 &
,因此 int&
.
Should I use the first or the second way?
这取决于您实际想要获得的类型。这两种方式的含义不同 - 您应该使用能够解决您要解决的直接问题的任何一种方式。
更一般地说,由于引用折叠规则,decltype(expr)&
总是左值引用。
decltype((expr))
可以是非引用纯右值(如 decltype((5))
)、左值引用(如 decltype((a))
)或右值引用(如 decltype((std::move(a)))
).
我试图更好地理解 decltype 以确定编译时表达式的类型。比方说我用一个双变量来做:
#include <iostream>
#include <type_traits>
int main(){
double a;
typedef decltype(a) a_type;
typedef decltype((a)) ref_a_type;
typedef decltype(a)& o_ref_a_type;
a_type b;
ref_a_type c = b;
o_ref_a_type d = b;
if (std::is_same<decltype(b), double>::value) std::cout << "b is double\n";
if (std::is_same<decltype(c), double&>::value) std::cout << "c is double&\n";
if (std::is_same<decltype(d), double&>::value) std::cout << "d is double&\n";
}
如果我没有理解错的话,这些观点应该是正确的:
decltype(a)
returnsdouble&
如果a
是左值,否则double
。- decltype 推导表达式的类型,除非它应用于变量,在这种情况下它推导该变量的类型。
- 如果变量被括号括起来,它就成为一个左值表达式。
因此,decltype((a))
和 decltype(a)&
在这种情况下是等价的,但并不总是等价的,例如,如果 a
不是变量:
typedef decltype((5)) ref_a_type;
typedef decltype(5)& o_ref_a_type;
则两种类型不等价(ref_a_type
是 int
而 o_ref_a_type
是 int&
,因为在这种情况下额外的括号是无用的)。有人可以对此做出更好的解释吗?我应该使用第一种还是第二种方式?
在我看来,第二种方式比第一种方式更具可读性和可理解性。
就 C++ 标准而言,decltype(e)
的规则非常清楚,所以我将复制它们(来自 [dcl.type.simple]):
For an expression
e
, the type denoted bydecltype(e)
is defined as follows:
(4.1) — ife
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 if e names a set of overloaded functions, the program is ill-formed;
(4.2) — otherwise, ife
is an xvalue,decltype(e)
isT&&
, whereT
is the type ofe
;
(4.3) — otherwise, ife
is an lvalue,decltype(e)
isT&
, whereT
is the type of e;
(4.4) — otherwise,decltype(e)
is the type ofe
.
因此请按顺序查看您的示例:
decltype(a)
:a
是一个未加括号的 id-expression, 所以这只是a
的类型:double
.decltype((a))
:现在有括号,所以我们跳过第一个项目符号。a
不是一个 xvalue,它是一个 lvalue,所以这是double&
。decltype(a)&
:又是第一种情况,所以是double&
。decltype((5))
:这既不是 id-expression(带括号或其他)、xvalue 或 lvalue - 它是 prvalue,所以我们转到获取表达式类型的最后一个项目符号:int
.decltype(5)&
:与最后一点相同,只是现在您明确添加了一个&
,因此int&
.
Should I use the first or the second way?
这取决于您实际想要获得的类型。这两种方式的含义不同 - 您应该使用能够解决您要解决的直接问题的任何一种方式。
更一般地说,由于引用折叠规则,decltype(expr)&
总是左值引用。
decltype((expr))
可以是非引用纯右值(如 decltype((5))
)、左值引用(如 decltype((a))
)或右值引用(如 decltype((std::move(a)))
).