web-dev-qa-db-ja.com

演算子+ =の右側に初期化子リストを使用できるのに、演算子+は使用できないのはなぜですか?

これは 中括弧で囲まれた初期化子をoperator+の引数として使用できない理由に関する以前の質問 のフォローアップです。これは this主題に関する以前の質問

次の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;
}

operator+を中括弧で囲まれた初期化子リストとともに使用するmainの行はコンパイルされません(そして、その前の質問をした後、これがなぜであるかがわかりました)。ただし、mainopeartor+=を使用するコードが実際に正常にコンパイルされる理由がわかりません。

+=をオーバーロードして問題なく動作させることができる理由について、正確に混乱していますが、+のオーバーロードはここでは機能しないようです。 +=演算子のコンテキストで中括弧で囲まれた初期化子を許可するが、+演算子は許可しない、標準の特定の規定はありますか?それとも、これは単なる奇妙なコンパイラの癖ですか?

23
templatetypedef

この質問 (リンクした質問からリンクされています)への回答で説明されています。

言語文法では、任意の式の代わりにではなく、特定の文法コンテキストでのみブレースリストを使用できます。このリストには、代入演算子の右側が含まれていますが、一般に演算子の右側は含まれていません。

+=は代入演算子ですが、+はそうではありません。

代入式の文法は次のとおりです。

代入式:条件式論理式または式の代入演算子初期化子句throw-expression代入演算子:= *= *= /= %= += -= >>= <<= &= ^= |= 
のいずれか 
22
M.M

C++14§5.17/ 9:

Abraced-init-listがの右側に表示される場合があります

  • スカラーへの割り当て。この場合、初期化子リストには最大で1つの要素が含まれます。 x={v}の意味(Tは式xのスカラー型)は、x=T{v}の意味です。 x={}の意味はx=T{}です。
  • クラス型のオブジェクトへの代入。この場合、初期化子リストは、オーバーロード解決(13.5.3、13.3)によって選択された代入演算子関数への引数として渡されます。

これは、a+=baとの$ 5.7/7の同等性を介して適用されます。 =a+b(ただし、a+=に対して1回だけ評価されます)。言い換えると、M.M。のコメントにより、組み込み演算子+=は同等であるため、特別な更新演算子ではなく、代入演算子と見なされます。したがって、「割り当て」に関する上記の引用テキストは、+=に適用されます。

10

+=演算子は複合代入です。この標準では、割り当ての右側に初期化子リストを明示的に許可しています。

§8.5.4/ 1 [...]注:リストの初期化を使用できます

.。

—割り当ての右側(5.17)

§5.17は、複合割り当てを含むすべての割り当てについて説明しています。

代入式:
-条件式
-logical-or-expression assignment-operator initializer-clause
-スロー式

代入演算子:の1つ
=*=/=%=+=-=>>=<<=&=ˆ=|=

7
dasblinkenlight