这是对an earlier question about why I can't use a brace-enclosed initializer as an argument to operator+
的跟进,通过查看this earlier question on the subject解决了这个问题。
考虑以下C ++代码,您可以try live at 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
的代码确实编译得很好。
我很困惑为什么我可以重载+=
并让它工作正常,而重载+
似乎无法在这里工作。标准中是否有一个特定条款允许在+=
运算符而不是+
运算符的上下文中使用括号括起的初始值设定项?或者这只是一个奇怪的编译怪癖?
答案 0 :(得分:22)
this question的答案中解释了这一点(与您链接的问题相关联)。
语言语法只允许某些语法上下文中的支撑列表,而不是任意表达式。该列表包括赋值运算符的右侧,但不包括运算符的右侧。
+=
是一个赋值运算符,+
不是。
赋值表达式的语法是:
assignment-expression: conditional-expression logical-or-expression assignment-operator initializer-clause throw-expression assignment-operator: one of= *= *= /= %= += -= >>= <<= &= ^= |=
答案 1 :(得分:10)
C ++14§5.17/ 9:
“ braced-init-list 可能会出现在
的右侧
- 对标量的赋值,在这种情况下,初始化列表最多只能包含一个元素。
x={v}
的含义T
是表达式x
的标量类型,是x=T{v}
的含义。x={}
的含义是x=T{}
。- 对类类型对象的赋值,在这种情况下,初始化列表作为参数传递给由重载决策(13.5.3,13.3)选择的赋值运算符函数。
这适用于 a +=
b ,其价格为$ 5.7 / 7等于 a =
+
b (除了 a 仅对+=
评估一次)。换句话说,由于M.M.的评论,因为内置运算符+=
的等价性被视为赋值运算符,而不是特殊的更新运算符。
因此,上面引用的关于“赋值”的文字适用于+=
。
答案 2 :(得分:7)
+=
运算符是复合赋值。该标准明确允许在赋值右侧的初始化列表:
§8.5.4/ 1 [...]注意:可以使用列表初始化
...
- 在作业的右侧(5.17)
§5.17谈论所有作业,包括复合作业:
赋值表达式:
- 条件表达式
- logical-or-expression assignment-operator initializer-clause
- throw-expression赋值操作符:中的一个
=
*=
/=
%=
+=
-=
>>=
<<=
&=
ˆ=
|=