9

I have a little piece of code which has a statement void();

int main() 
{
   void( ); // 1: parses fine in GCC 5.4.0 -Wpedantic 
   // void;    // 2: error declaration does not declare anything
} 

What is 1 void() exactly?

  • An anonymous function declaration?
  • A type declaration?
  • An empty expression?

What makes 1 void() different from 2 void;?

I have read already:

  1. Is sizeof(void()) a legal expression? but there void() is considered a type in sizeof
  2. What does the void() in decltype(void()) mean exactly? where it is considered in declspec.
  3. And I read Is void{} legal or not?

But I am curious if the loose statement void(); is different from one of those (and why of course)

Community
  • 1
  • 1
André
  • 18,348
  • 6
  • 60
  • 74
  • I suspect void() is analogous to e.g. int pi = int(3.14); ... except that instead of casting 3.14 to an int, you are casting an empty expression to type void (and then ignoring the result, which you have to do anyway since it's of type void). – Jeremy Friesner Mar 29 '17 at 14:37
  • 1
    related: http://stackoverflow.com/questions/39279074/what-does-the-void-in-decltypevoid-mean-exactly I'm trying to find a better dupe – NathanOliver Mar 29 '17 at 14:38
  • could be useful in templates so you don't have to specialize for void? – Karoly Horvath Mar 29 '17 at 14:39
  • 1
    For those people pointing me to possible dupes: Most of the related questions are asked by user skypjack similar to the one I have put in the question. But I have not seen a case where the "loose statement" void(); is considered, but only in the context of decltype, sizeof, etc. – André Mar 29 '17 at 14:40
  • `void()` is often used as a type for a function which takes no arguments and returns no value. – Some programmer dude Mar 29 '17 at 14:40
  • 4
    Maybe: http://stackoverflow.com/questions/37701321/construction-of-a-void-type – NathanOliver Mar 29 '17 at 14:41
  • It's #3. Same category as `int;` failing but `int()` not. – Hatted Rooster Mar 29 '17 at 14:46
  • @GillBates. Do you mean #3 as in it is a dupe of "Is void{} legal or not" or #3 as in the third bullet: it is an empty expression? – André Mar 29 '17 at 14:52
  • @Andre, It's an empty expression. `void()` is an expression with special meaning. It's also a function type in some contexts. – chris Mar 29 '17 at 14:53
  • @andre Bullet point – Hatted Rooster Mar 29 '17 at 15:01
  • @NathanOliver the answer by "chris" on your latest dupe is good, I'll go with that – M.M Mar 29 '17 at 20:04
  • @M.M Sounds good. – NathanOliver Mar 29 '17 at 20:07
  • actually I changed my mind ... the difference between `void;` and `void();` needs some explanation , since they can both be *type-id*s , and the dupe doesn't cover that. Writing answer now – M.M Mar 29 '17 at 20:16

2 Answers2

4

void; is an error because there is no rule in the language grammar which matches that code. In particular, there is no rule type-id ;,

However, the code void() matches two grammar rules:

  1. type-id .
  2. postfix-expression, with the sub-case being simple-type-specifier ( expression-list-opt ).

Now, the parser needs to match void(); to a grammar rule. Even though void() matches type-id, as mentioned earlier there is no rule that would match type-id ;. So the parser rejects the possible parsing of void() as type-id in this context, and tries the other possibility.

There is a series of rules defining that postfix-expression ; makes a statement. So void() is unambiguously parsed as postfix-expression in this context.

As described by the other answers you linked already, the semantic meaning of this code as a postfix-expression is a prvalue of type void.

Related link: Is sizeof(int()) a legal expression?

Community
  • 1
  • 1
M.M
  • 138,810
  • 21
  • 208
  • 365
  • [stmt.ambig] is the closer disambiguation rule here, I think. Of course, there's no ambiguity in the first place. – T.C. Mar 30 '17 at 02:28
  • @T.C. I've edited, hopefully it is more accurate now. I'm not an expert in parsing, feel free to tidy anything up – M.M Mar 30 '17 at 02:37
  • And to be precise: This postfix-expression is an explicit cast? According to "http://en.cppreference.com/w/cpp/language/explicit_cast", number four actually has specific explanation for void: *If new_type is (possibly cv-qualified) void, the expression is a void prvalue without a result object (since C++17).* I could not find a corresponding statement in the standard – André Mar 30 '17 at 06:51
  • 1
    @Andre the "result object" stuff is new in C++17, [basic.lval]/2 in N4618 has the text which your cppreference quote is based on. – M.M Mar 30 '17 at 07:55
0

A void expression.

The compiler won't create any code for it, e.g.,

in VS

_asm
{
    nop;
}
void();
_asm
{
    nop;
}

produces this assembly:

_asm
{
    nop;
003017CE  nop  
}
void();
_asm
{
    nop;
003017CF  nop  
}
peedurrr
  • 187
  • 16