geza
geza

Reputation: 29912

Type of expression consisting only of a variable identifier

cppreference says:

An identifier that names a variable, a function, specialization of a concept, (since C++20) or an enumerator can be used as an expression. The result of an expression consisting of just the identifier is the entity named by the identifier. [...] The type of the expression is determined as follows:

[...] Otherwise, the type of the expression is the same as the type of the entity named.

Isn't it a bug? If the entity is a reference, like:

int &a = ...

Then a's type as an entity is int &, but a's type as an expression is only int, isn't it? An expression's type is never a reference:

[...] Each expression has some non-reference type

Bonus question: does it matter, whether a's type (as an expression) is int or int &? If yes, where does it make a difference?


Note: the same wording is used at decltype:

If the argument is an unparenthesized id-expression or an unparenthesized class member access expression, then decltype yields the type of the entity named by this expression.

But clearly, decltype(a) is int &.

Upvotes: 2

Views: 145

Answers (2)

Rakete1111
Rakete1111

Reputation: 48918

Isn't it a bug?

No. The type of a is int. Yeah true that this is only before the type adjustment, but since that always happens, it makes no sense to talk about expressions having reference type, since the reference disappears immediately.

does it matter, whether a's type (as an expression) is int or int &? If yes, where does it make a difference?

This is basically asking why we need value categories at all. Basically it would break move semantics because of rvalue references that are sometimes xvalues and sometimes lvalues.

Upvotes: 0

eerorika
eerorika

Reputation: 238281

This is what standard (draft) says:

[expr.type] Expressions / Type

If an expression initially has the type “reference to T”, the type is adjusted to T prior to any further analysis. ...

So, clearly an expression can have a reference type - initially, before adjustment for type analysis.

"Each expression has some non-reference type" is not true?

Depends on how you interpret it. An expression can have a non-reference type (initially), but all expressions have some non-reference type (after adjustment) that is used for type analysis.

[expr.prim.id.unqual] Expressions / Unqualified names

The result is the entity denoted by the identifier. ... If the entity is a template parameter object for a template parameter of type T ... [does not apply] ... Otherwise, the type of the expression is the type of the result. [Note: The type will be adjusted as described in 7.2.2 if it is cv-qualified or is a reference type. — end note] ... [Example:

void f() {
    float x, &r = x;
    [=] {
        decltype(x) y1;        // y1 has type float
        decltype((x)) y2 = y1; // y2 has type float const& because this lambda
                               // is not mutable and x is an lvalue
        decltype(r) r1 = y1;   // r1 has type float&
        decltype((r)) r2 = y2; // r2 has type float const&

    };
}

— end example]


Decltype specifiers [dcl.type.decltype]

... if e is an unparenthesized id-expression or ..., decltype(e) is the type of the entity named by e.

Upvotes: 1

Related Questions