Почему я могу использовать списки инициализаторов в правой части оператора +=, но не оператора +?

Это продолжение предыдущего вопроса о том, почему я не могу использовать инициализатор в скобках в качестве аргумента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 рассказывает обо всех назначениях, включая составные:

Назначение выражение:
- условно-выражение
- предложение инициализатора оператора логического или или выражения
- бросить выражение

оператор присваивания: один из
=*=/=%= +=-=>>=<<=&=ˆ=|=

Другие вопросы по тегам