Разбирая проблему, я имею в виду ее сущность, я могу инициализировать переменную как int, выполнив вначале лямбду бездействия в выражении через запятую, например так:
int main(){
auto x = ( []{}(), 10 ); // same effect as auto x = 10;
}
Но если я не заключу в скобки инициализирующее выражение,
int main(){
auto y = []{}(), 10; // won't compile
}
все gcc, clang и MSVC жалуются на попытки инициализации y
с void
выражение.
Почему я должен заключить в скобки выражение запятой, чтобы использовать его в качестве инициализатора?
В декларации ,
Символ отделяет деклараторов. Более простой пример:
int i = 2, j = 3; // OK: declares `i` and `j`
int i = 2, 3; // Error: `3` is not a declarator
Во втором случае это выглядит неоднозначно. Это ,
разделители, или это ,
часть выражения 2, 3
?
Чтобы устранить эту неоднозначность, мы можем обратиться к грамматике языка (C ++ 14 [dcl.decl]):
простая декларация:
Децл-спецификатор-слвыбирать INIT-описатель-листвыбирать;
атрибут-спецификатор-seq decl-спецификатор-seqвыбирать INIT-описатель-лист;
INIT-описатель-лист:
INIT-описатель
INIT-описатель-лист,
INIT-описательINIT-описатель:
инициализатор объявлениявыбирать
То, как работают грамматики, это означает, что при разборе объявления самая длинная последовательность, которая соответствует INIT-описатель ,
Считается. (Это иногда называют «принципом максимального жаворонка»). Так int i = 2,
Матчи INIT-описатель ,
. затем 3
не соответствует init-declarator
, так что разбора не получается.
Других решений пока нет …