I found they're different, and the language standard says what kind of type each statement should retrieve(difference between variable and expression). But I really wish to know why these 2 kinds of types should be 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;
}
The running result is '2,3'
So why decltype((int))
is int&
by design, what's the consideration of C++ language design here? Any syntax consistency that requires such a design? (I don't wish to get "This is by design")
Thanks for your explanations.
'auto' lets you declare a variable with a particular type whereas decltype lets you extract the type from the variable so decltype is sort of an operator that evaluates the type of passed expression.
If the expression parameter is a call to a function or an overloaded operator function, decltype(expression) is the return type of the function. Parentheses around an overloaded operator are ignored. If the expression parameter is an rvalue, decltype(expression) is the type of expression .
To get the datatype of variable, use typeid(x). name() of typeinfo library. It returns the type name of the variable as a string.
The documentation states that it is "useful primarily to developers who write template libraries." decltype was added to the mainline of the GCC C++ compiler in version 4.3, released on March 5, 2008.
If you read e.g. this decltype
reference you will see
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&
;
[Emphasis mine]
And then a little further down the note
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.
Because you use a parenthesized expression it is treated as an lvalue, meaning that 3.b above is active and decltype((x))
gives you int&
if x
is int
.
It should be noted that while the reference isn't authoritative it is derived from the specification and generally reliable and correct.
From the C++11 specification ISO/IEC 14882:2011, section 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
And with an example:
struct A { double x; }; const A* a = new A(); ... decltype((a->x)) x4 = x3; // type is const double&
Basically exactly what the previously linked reference said.
With your example, e
in the specification is (x)
(since you have declspec((x))
). Now the first case doesn't fit because (x)
is not an unparenthesized expression. The second case doesn't fit because (x)
isn't an xvalue. The third case matches though, (x)
is an lvalue of type int
, leading decltype((x))
to be int&
.
So the answer to your query is simply: Because the specification says so.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With