Действительно, окончательная версия C++11 не позволяет использовать списки инициализаторов с правой стороны (или с левой стороны, если уж на то пошло) бинарного оператора.
Во-первых, списки-инициализаторы не являются выражениями, как определено в §5 Стандарта. Аргументы функций, а также бинарных операторов, как правило, должны быть выражениями, а грамматика для выражений, определенная в §5, не включает синтаксис для списков инициализации фигурных скобок (т. е. чистых списков инициализаторов; обратите внимание, что имя типа < em>за которым следует скобочный список-инициализации, например, bar {2,5,"hello",7}
— это выражение).
Чтобы можно было удобно использовать чистые списки инициализаторов, стандарт определяет различные исключения, которые резюмируются в следующем (ненормативном) примечании:
§8.5.4/1 [...] Примечание. Можно использовать инициализацию списка
— как инициализатор в определении переменной (8.5)
— как инициализатор в новое выражение (5.3.4)
— в операторе возврата (6.6.3)
— как аргумент функции (5.2.2)
— как индекс (5.2.1)< br/> — как аргумент вызова конструктора (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"}]
является допустимым), а последний пункт позволяет правая часть присваивания (но не общие бинарные операторы).
Для бинарных операторов такого исключения нет, таких как +
, *
или <<
, поэтому вы не можете поместить чистый список инициализаторов (т. е. тот, которому не предшествует имя типа) ни с одной стороны от них.
Что касается причин для этого, черновик/дискуссионный документ N2215, написанный Страуструпом и Дос Рейсом в 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] в качестве левых аргументов для большинства операторов — это слишком большая [...]
Другими словами, списки инициализаторов не включены в правой части, потому что они не включены в левой части, и они не включены в левой части, потому что это создало бы слишком большую проблему для синтаксических анализаторов.
Интересно, можно ли упростить проблему, выбрав другой символ вместо фигурных скобок для синтаксиса списка инициализаторов.
person
jogojapan
schedule
12.07.2012
operator<<
, чтобы взятьinitializer_list<>
на RHS... Каков ваш фактический вопрос? - person ildjarn   schedule 10.07.2012baz << bar{1, 2, 3, 4, 5};
, но, похоже, преобразования не происходит. - person mavam   schedule 10.07.2012bar
неявный конструктор, который принимает одинinitializer_list<>
. - person ildjarn   schedule 10.07.2012initializer_list
имеет ровно один параметр шаблона, в отличие от конструктора с переменным числом аргументов, имеющего несколько типов аргументов. - person mavam   schedule 10.07.2012operator<<(baz, {1, -2, "foo", 4, 5});
работает. - person mfontanini   schedule 11.07.2012