これは 中括弧で囲まれた初期化子を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
の行はコンパイルされません(そして、その前の質問をした後、これがなぜであるかがわかりました)。ただし、main
でopeartor+=
を使用するコードが実際に正常にコンパイルされる理由がわかりません。
+=
をオーバーロードして問題なく動作させることができる理由について、正確に混乱していますが、+
のオーバーロードはここでは機能しないようです。 +=
演算子のコンテキストで中括弧で囲まれた初期化子を許可するが、+
演算子は許可しない、標準の特定の規定はありますか?それとも、これは単なる奇妙なコンパイラの癖ですか?
この質問 (リンクした質問からリンクされています)への回答で説明されています。
言語文法では、任意の式の代わりにではなく、特定の文法コンテキストでのみブレースリストを使用できます。このリストには、代入演算子の右側が含まれていますが、一般に演算子の右側は含まれていません。
+=
は代入演算子ですが、+
はそうではありません。
代入式の文法は次のとおりです。
代入式:条件式論理式または式の代入演算子初期化子句throw-expression代入演算子:= *= *= /= %= += -= >>= <<= &= ^= |=
のいずれか
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+=
bにaとの$ 5.7/7の同等性を介して適用されます。 =
a+
b(ただし、aは+=
に対して1回だけ評価されます)。言い換えると、M.M。のコメントにより、組み込み演算子+=
は同等であるため、特別な更新演算子ではなく、代入演算子と見なされます。したがって、「割り当て」に関する上記の引用テキストは、+=
に適用されます。
+=
演算子は複合代入です。この標準では、割り当ての右側に初期化子リストを明示的に許可しています。
§8.5.4/ 1 [...]注:リストの初期化を使用できます
.。
—割り当ての右側(5.17)
§5.17は、複合割り当てを含むすべての割り当てについて説明しています。
代入式:
-条件式
-logical-or-expression assignment-operator initializer-clause
-スロー式代入演算子:の1つ
=
*=
/=
%=
+=
-=
>>=
<<=
&=
ˆ=
|=