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

2

7

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.

Paternal answered 21/2, 2017 at 9:11 Comment(3)
@some i dont see an explanation thereHalfcaste
@JohannesSchaub-litb Added answer with quotesUnexpressive
Your best chance is to read the proposals for "decltype", I think. Googling for "decltype wg21 proposal" gives a few interesting papers.Halfcaste
U
3

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.

Unexpressive answered 21/2, 2017 at 9:36 Comment(10)
I don't see an explanation here for this behavior.Halfcaste
Thanks, but I don't see any explanation here, it's just a replication of my question, I was asking why they differ?Paternal
@HindForsum I'll try to find the relevant parts from the specification after lunch. But you will see that they say just the same. So the real answer will simply be: Because the specification says so!Unexpressive
@Someprogrammerdude the comment does not make sense. Are you saying that this was added to the specification because the specification says so? That's above my head, I'm outHalfcaste
@JohannesSchaub-litb I'm saying the reference says what is says, because the specification says so.Unexpressive
I think @JohannesSchaub-litb was -- like the OP, who was explicit about it -- looking for a rationale (after all, it is afaict the only place where parentheses around an expression change the semantics of a program), rather than a formal explanation for the program's behavior. My take is that depending on the use case the programmer wants to be able to obtain the literal type that e has (no parentheses) or a reference. The parentheses serve as a means to express the respective desire in the language without introducing new syntax elements or keywords. It's a kludge, like so much in C++.Ozuna
@PeterA.Schneider Ah of course, that makes sense. In that case the question is really unanswerable by anyone who wasn't part of the standards committee really. All everyone else can do is guess, making the question kind of pointless.Unexpressive
One may contend that on the contrary, questions which are not answered in standards are the actually interesting ones ;-).Ozuna
@Someprogrammerdude "in that case the question is really unanswerable by anyone who wasn't part of the standards committee really." that is not correct. Anyone who has a reference to a text or has read a text from someone who coined the rules is qualified to answer it.Halfcaste
But that does not mean that anyone else is free to guess the answer. That would be true on IRC or usenet or other discussion forums, or for the "comment" field of the question. I for example am not qualified to answer, therefore I just left a comment on the question.Halfcaste
Q
3

Well, The answer I see here is that "the specification says so". I looked into stroustrup's original drafts of decltype and this is what it says.

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.

Look at the last statement here, I think that explains. Since parenthesis are built-in operators to indicate and expression.

Questionable answered 21/3, 2018 at 14:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.