Boiling a problem I'm having down to its essence, I can initialize a variable as an int by first executing a do-nothing lambda in a comma expression like this:
int main(){
auto x = ( []{}(), 10 ); // same effect as auto x = 10;
}
But if I don't parenthesize the initializing expression,
int main(){
auto y = []{}(), 10; // won't compile
}
all of gcc, clang, and MSVC complain about trying to initialize y with a void expression.
Why do I have to parenthesize the comma expression to use it as an initializer?
In a declaration, the , symbol separates declarators. A simpler example:
int i = 2, j = 3; // OK: declares `i` and `j`
int i = 2, 3; // Error: `3` is not a declarator
In the second case, it looks ambiguous. Is the , separating declarators, or is the , part of an expression 2, 3?
To resolve this ambiguity we can consult the language grammar (C++14 [dcl.decl]):
simple-declaration:
decl-specifier-seqopt init-declarator-listopt;
attribute-specifier-seq decl-specifier-seqopt init-declarator-list;init-declarator-list:
init-declarator
init-declarator-list,init-declaratorinit-declarator:
declarator initializeropt
The way grammars work, this means that when parsing a declaration the longest possible sequence that matches init-declarator , is considered. (This is sometimes called "maximum munch principle"). So int i = 2, matches init-declarator , . Then 3 fails to match init-declarator, so parsing fails.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With