Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++11 why the type of 'decltype(x)' and 'decltype((x))' are different?

Tags:

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.

like image 594
Hind Forsum Avatar asked Feb 21 '17 09:02

Hind Forsum


People also ask

What is the difference between auto and decltype?

'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.

What is the return type of decltype?

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 .

How do you determine the type of a variable in C++?

To get the datatype of variable, use typeid(x). name() of typeinfo library. It returns the type name of the variable as a string.

When did C++ add decltype?

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.


1 Answers

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 yields T&;

[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) and decltype((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 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

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.

like image 68
Some programmer dude Avatar answered Sep 22 '22 10:09

Some programmer dude