这是之前关于为什么我不能使用大括号括起来的初始值设定项作为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+
行无法编译(并且在提出前面的问题之后,我现在知道为什么会这样)。但是,我很困惑为什么在main
中使用operator+=
的代码确实可以很好地编译。
我很困惑为什么我可以重载+=
并让它正常工作,而重载+
在这里似乎不起作用。标准中是否有特定规定允许在+=
运算符的上下文中使用大括号括起来的初始值设定项,但不允许在+
运算符中使用?或者这只是一个奇怪的编译器怪癖?
这个问题的答案中有解释(从您链接到的问题链接)。
语言语法只允许在某些语法上下文中使用大括号列表,而不是代替任意表达式。 该列表包括赋值运算符的右侧,但不包括一般运算符的右侧。
+=
是赋值运算符,+
不是。
赋值表达式的语法为:
赋值表达式:条件表达式逻辑或表达式赋值运算符初始值设定项子句抛出表达式赋值运算符:之一= *= *= /= %= += -= >>= <<= &= ^= |=
C++14 §5.17/9:
">一个带大括号的初始化列表可能会出现在
- 标量的赋值,在这种情况下,初始值设定项列表最多应具有单个元素。
x={v}
的意思,其中T
是表达式x
的标量类型,是x=T{v}
的意思。x={}
的意思是x=T{}
。- 对类类型的对象的赋值,在这种情况下,初始值设定项列表将作为参数传递给重载解析 (13.5.3、13.3) 选择的赋值运算符函数。
这适用于+=
b,因为它的 $5.7/7 等价于=
a+
b(除了a只对+=
进行一次评估)。换句话说,由于 M.M. 的评论,由于内置运算符的等效性+=
被视为赋值运算符,而不是特殊的更新运算符。 因此,上面引用的关于"转让"的文字适用于+=
。
+=
运算符是一个复合赋值。该标准明确允许在赋值的右侧使用初始值设定项列表:
§8.5.4/1 [...]注意:可以使用列表初始化
。
— 在作业的右侧 (5.17)
§5.17 讨论了所有作业,包括复合作业:
赋值表达式:
- 条件表达式 - 逻辑或表达式赋值运算符初始值设定项子句
- 抛出表达式赋值运算符:以下之一
=
*=
/=
%=
+=
-=
>>=
<<=
&=
ˆ=
|=