Почему я могу использовать списки инициализаторов в правой части оператора +=, но не оператора +?
Это продолжение предыдущего вопроса о том, почему я не могу использовать инициализатор в скобках в качестве аргументаoperator+
, который был решен путем рассмотрения этого более раннего вопроса на эту тему.
Рассмотрим следующий код C++, который вы можете попробовать вживую на ideone.com:
#include <iostream>
#include <initializer_list>
using namespace std;
struct AddInitializerList {
void operator+= (initializer_list<int> values) {
// Do nothing
}
void operator+ (initializer_list<int> values) {
// Do nothing
}
};
int main() {
AddInitializerList adder;
adder += {1, 2, 3}; // Totally legit
adder + {1, 2, 3}; // Not okay!
return 0;
}
Линия в main
который использует operator+
с заключенным в скобки списком инициализатора не компилируется (и, после того, как задал этот предыдущий вопрос, теперь я знаю, почему это так). Тем не менее, я запутался, почему код, который использует opeartor+=
в main
действительно компилируется просто отлично.
Я не совсем понимаю, почему я могу перегрузить +=
и работать нормально, при перегрузке +
кажется, не работает здесь. Есть ли в стандарте конкретное положение, разрешающее инициализаторы в скобках в контексте +=
оператор, но не +
оператор? Или это просто странная причуда компилятора?
3 ответа
Это объясняется в ответе на этот вопрос (который связан с вопросом, на который вы ссылались).
Языковая грамматика допускает ограниченный список только в определенных грамматических контекстах, а не вместо произвольного выражения. Этот список включает в себя правую часть операторов присваивания, но НЕ правую часть операторов в целом.
+=
является оператором присваивания, +
не является.
Грамматика для выражений присваивания:
Назначение выражение: условно-выражение оператор инициализации оператора логического или-выражения вбрасывание выражение оператор присваивания: один из= *= *= /= %= += -= >>= <<= &= ^= |=
C++14 §5.17/9:
" Справочный список скобок может появиться в правой части
- присваивание скаляру, и в этом случае список инициализатора должен содержать не более одного элемента. Значение
x={v}
, гдеT
скалярный тип выраженияx
это что изx=T{v}
, Значениеx={}
являетсяx=T{}
,- присваивание объекту типа класса, и в этом случае список инициализатора передается в качестве аргумента функции оператора присваивания, выбранной с помощью разрешения перегрузки (13.5.3, 13.3).
Это относится к +=
б через его $5,7/7 эквивалентность а =
+
б (за исключением того, что а оценивается только один раз для +=
). Другими словами, из-за комментария MM, из-за эквивалентности для встроенных операторов +=
рассматривается как оператор присваивания, а не как специальный оператор обновления. Следовательно, приведенный выше текст о "уступке" относится к +=
,
+=
оператор является составным назначением. Стандарт явно разрешает списки инициализаторов в правой части назначений:
§8.5.4 / 1 [...] Примечание: можно использовать инициализацию списка
...
- в правой части задания (5.17)
§5.17 рассказывает обо всех назначениях, включая составные:
Назначение выражение:
- условно-выражение
- предложение инициализатора оператора логического или или выражения
- бросить выражениеоператор присваивания: один из
=
*=
/=
%=
+=
-=
>>=
<<=
&=
ˆ=
|=