31

This is a follow-up of this question, more precisely of the comments of this answer.

What does the void() in decltype(void()) represent exactly?
Does it represent a function type, an expression or whatever?

Community
  • 1
  • 1
skypjack
  • 49,335
  • 19
  • 95
  • 187

2 Answers2

22

Using a hyperlinked C++ grammar, the parsing of decltype(void()) is:

decltype( expression )
decltype( assignment-expression )
decltype( conditional-expression )

... lots of steps involving order of operations go here ...

decltype( postfix-expression )
decltype( simple-type-specifier ( expression-listopt ) )
decltype( void() )

So void() is a kind of expression here, in particular a postfix-expression.

Specifically, quoting section 5.2.3 [expr.type.conf] paragraph 2 of the 2011 ISO C++ standard:

The expression T(), where T is a simple-type-specifier or typename-specifier for a non-array complete object type or the (possibly cv-qualified) void type, creates a prvalue of the specified type, which is value-initialized (8.5; no initialization is done for the void() case).

So void() is an expression of type void, just as int() is an expression of type int (with value 0). Clearly a void expression has no value, but here it's the operand of decltype, so it's not evaluated. decltype refers only to its operand's type, not its value.

decltype(void()) is simply a verbose way of referring to the type void.

Jeffrey Bosboom
  • 13,313
  • 16
  • 79
  • 92
Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
  • 2
    @skypjack: See the C++11 standard (or a draft), section 5.2.3 [expr.type.conv], paragraph 2. A *simple-type-specifier* followed by empty parentheses "creates a prvalue of the specified type,which is valueinitialized (8.5; no initialization is done for the void() case)". Just as `int()` is an expression of type `int`, `void()` is an expression of type `void`. And since it's the operand of `decltype`, it's not evaluated. `decltype(void())` is just a complex way of referring to the type `void`. (Yakk, you might want to expand your answer to explain how `void()` is an expression.) – Keith Thompson Sep 01 '16 at 20:00
  • 1
    @Yakk As already mentioned in the comments, expanding the answer with more details would help. +1 to promote the suggestion. Thank you. – skypjack Sep 01 '16 at 20:18
  • 3
    I've taken the liberty of adding an explanation of what `void()` means. Please check my update for accuracy. – Keith Thompson Sep 01 '16 at 20:50
6

I'm quoting the comment of @JoachimPileborg that seems to explain it correctly:

I think I figured it out now, decltype needs an expression, and not a type. void() is not actually a type here, but an expression, a C-style cast (just like e.g. int(12.34)) void(void) is not an expression therefore it doesn't work. How the compiler parses different things depends on the context, when it expects a type it parses as a type, when it expects an expression it parses as an expression. sizeof() (with the parentheses) expects first of all a type, otherwise it's parsed as a parenthesized expression.

I'm not looking for credits or reputation.
Anyway, I guess that was an interesting answer in the answer that is worth of a dedicated question for future readers.

Community
  • 1
  • 1
skypjack
  • 49,335
  • 19
  • 95
  • 187
  • If you don't want rep, you can mark the answer as Community Wiki – AndyG Sep 01 '16 at 19:06
  • @skypjack click "edit" then check the box "community wiki" below the text window – TemplateRex Sep 01 '16 at 19:11
  • 3
    `void()` is not a C-style cast. In C, a cast consists of a parenthesized type name followed by an expression, for example `(void)42`. In `void()`, the type name is not parenthesized and it's not followed by an expression. – Keith Thompson Sep 01 '16 at 19:38
  • @KeithThompson Feel free to add your own question. As you can see, there is not an accepted one. – skypjack Sep 01 '16 at 19:44