Significance of parentheses in decltype((c))?

  • c is the name of a variable;

  • (c) is an expression, in this case an lvalue expression, whose value is identical to the value of the variable c.

And the two are treated differently by decltype. Consider, for example, decltype(1+2), which is also an example taking an expression. It just so happens that your example is a simple version of an expression: one which merely names a single variable and does nothing exciting with it.

It's one of those differences that you generally only really care about if you're rationalising about the subtle parts of the language specification; though, as you have identified, it has quite a significant practical effect in this case.

Please note though that there is no operator usage here. It's all simply a deduction from the layout of the grammar.


I found a good description here. It describes the difference between:

struct A { double x; };
const A* a = new A();
...
decltype(a->x) x4; // type is double
decltype((a->x)) x5; // type is const double&

and I quote:

The reason for the difference between the latter two invocations of decltype is that the parenthesized expression (a->x) is neither an id-expression nor a member access expression, and therefore does not denote a named object. [13]

Because the expression is an lvalue, its deduced type is "reference to the type of the expression", or const double&. [10]