Ответ 1
В самом деле, окончательная версия С++ 11 не позволяет использовать списки инициализаций с правой стороны (или, если нужно, с левой стороны) двоичного оператора.
Во-первых, списки инициализаторов не являются выражениями, как определено в § 5 Стандарта. Аргументы функций, а также двоичных операторов обычно должны быть выражениями, а грамматика для выражений, определенных в § 5, не включает синтаксис списков перекрестных списков (то есть чистых списков инициализаторов; например, bar {2,5,"hello",7}
- это выражение).
Чтобы иметь возможность удобно использовать чистые списки инициализаторов, стандарт определяет различные исключения, которые суммируются в следующей (ненормативной) заметке:
§8.5.4/1 [...] Примечание: можно использовать инициализацию списка
- как инициализатор в переменной определении (8.5)
- как инициализатор в новом выражении (5.3.4)
- в заявлении о возврате (6.6.3)
- как аргумент функции (5.2.2)
- в качестве индекса (5.2.1)
- в качестве аргумента для вызова конструктора (8.5, 5.2.3)
- как инициализатор для нестатического элемента данных (9.2)
- в mem-инициализаторе (12.6.2)
- в правой части задания (5.17)
[...]
Четвертый пункт выше явно разрешает чистые инициализационные списки в качестве аргументов функции (поэтому работает operator<<(baz, {1, -2, "foo", 4, 5});
), пятый - в выражении в нижнем индексе (т.е. как аргумент operator[]
, например mymap[{2,5,"hello"}]
является законным), а последний элемент разрешает их в правой части назначений (но не общих двоичных операторов).
Существует не такое исключение для бинарных операторов, например +
, *
или <<
, поэтому вы не можете поместить чистый список инициализаторов (то есть тот, которому не предшествует typename) по обе стороны от них.
Что касается причин для этого, проект проект/дискуссионный документ N2215 от Stroustrup и Dos Reis с 2007 года предусматривает много понимания многих проблем с списками инициализаторов в различных контекстах. В частности, существует раздел о бинарных операторах (раздел 6.2):
Рассмотрим более общее использование списков инициализаторов. Например:
v = v+{3,4}; v = {6,7}+v;
Когда мы рассматриваем операторы как синтаксический сахар для функций, мы, естественно, рассмотрим вышеописанное значение
v = operator+(v,{3,4}); v = operator+({6,7},v);
Поэтому естественно распространять использование списков инициализаций в выражения. Существует много применений, когда списки инициализаторов в сочетании с операторами являются "естественными" обозначениями.
Однако нетривиально написать грамматику LR (1), которая позволяет произвольно использовать списки инициализаторов. Блок также начинается с {, поэтому включение списка инициализаторов в качестве первого (самого левого) объекта выражения приведет к хаосу в грамматике.
Тривиально разрешить списки инициализаторов в качестве правого операнда двоичных операторов, в индексы и аналогичные отдельные части грамматики. Реальная проблема заключается в том, чтобы позволить;a={1,2}+b;
как присваивать-инструкцию без разрешения;{1,2}+b;
. Мы подозреваем, что включение списков инициализаторов как правых, но и [sic] в качестве левых аргументов большинству операторов является слишком большим количеством kludge, [...]
Другими словами, списки инициализаций не включены с правой стороны, потому что они не включены с левой стороны, и они не включены с левой стороны, потому что это могло бы поставить слишком большая проблема для парсеров.
Интересно, можно ли упростить эту проблему, выбрав другой символ вместо фигурных скобок для синтаксиса списка инициализаторов.