为什么我可以在 operator += 的右侧使用初始化列表而不是 operator+?

Why can I use initializer lists on the right-hand side of operator += but not operator+?

这是 an earlier question about why I can't use a brace-enclosed initializer as an argument to operator+, which was resolved by looking at 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+ 与大括号括起来的初始化列表一起使用的行无法编译(而且,在问了之前的问题之后,我现在知道这是为什么了)。但是,我很困惑为什么在 main 中使用 operator+= 的代码确实编译得很好。

我很困惑为什么我可以重载 += 并让它工作得很好,而重载 + 在这里似乎不起作用。标准中是否有特定条款允许在 += 运算符而不是 + 运算符的上下文中使用大括号括起来的初始值设定项?或者这只是一个奇怪的编译器怪癖?

+= 运算符是一个 复合赋值 。该标准明确允许赋值右侧的初始化列表:

§8.5.4/1 [...] Note: List-initialization can be used

...

— on the right-hand side of an assignment (5.17)

§5.17 讨论所有作业,包括复合作业:

assignment-expression:
- conditional-expression
- logical-or-expression assignment-operator initializer-clause
- throw-expression

assignment-operator: one of
= *= /= %= += -= >>= <<= &= ˆ= |=

this question 的答案中有解释(链接自您链接到的问题)。

语言语法只允许在某些语法上下文中使用大括号列表,而不是任意表达式的位置。该列表包括赋值运算符的右侧,但不包括一般运算符的右侧。

+=是赋值运算符,+不是。

赋值表达式的语法是:

  assignment-expression:
     conditional-expression
     logical-or-expression assignment-operator initializer-clause
     throw-expression
  assignment-operator: one of
      = *= *= /= %= += -= >>= <<= &= ^= |=
  

C++14 §5.17/9:

A braced-init-list may appear on the right-hand side of

  • an assignment to a scalar, in which case the initializer list shall have at most a single element. The meaning of x={v}, where T is the scalar type of the expression x, is that of x=T{v}. The meaning of x={} is x=T{}.
  • an assignment to an object of class type, in which case the initializer list is passed as the argument to the assignment operator function selected by overload resolution (13.5.3, 13.3).

这适用于 a+=b 通过其 $5.7/7 等价于 a=a+b(除了 a 是仅对 += 评估一次)。换句话说,由于 M.M 的评论,由于内置运算符的等价性 += 被视为赋值运算符,而不是特殊的更新运算符。 因此,上面引用的关于“赋值”的文字适用于 +=.