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

tem*_*def 22 c++ operator-overloading initializer-list

这是一个早期问题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;
}
Run Code Online (Sandbox Code Playgroud)

在该生产线main使用operator+了括号内的初始化列表不编译(和,问这个问题前面经过,我现在知道这是为什么).但是,我很困惑为什么使用opeartor+=in 的代码main确实编译得很好.

我很困惑,为什么我可以重载+=并让它工作得很好,而重载+似乎在这里不起作用.标准中是否有特定的规定允许在+=操作员的情况下使用支架封闭的初始化器而不是+操作员?或者这只是一个奇怪的编译器怪癖?

M.M*_*M.M 21

这个问题的答案 (与您链接的问题相关联)对此进行了解释.

语言语法只允许某些语法上下文中的支撑列表,而不是任意表达式.该列表包括赋值运算符的右侧,但不包括运算符的右侧.

+=是一个赋值运算符,+不是.

赋值表达式的语法是:

__PRE__

  • @ Cheersandhth.-Alf OP,逐字地说,"标准中是否有一个特定条款允许在+ =运算符但不运行+运算符的情况下使用括号括起的初始值设定项?" (2认同)

Che*_*Alf 10

C++14§5.17/ 9:

"一个支撑-初始化列表上可能出现的右侧

  • 标量的赋值,在这种情况下,初始化列表最多只能包含一个元素.的含义x={v},在这里T是表达的标量类型x,是的x=T{v}.意思x={}x=T{}.
  • 对类类型的对象的赋值,在这种情况下,初始化列表作为参数传递给由重载决策(13.5.3,13.3)选择的赋值运算符函数.

这适用于一个+=b经由其$ 5.7/7等价于一个=一个+b(不同之处在于一个只计算一次对+=).换句话说,由于MM的评论,因为内置运算符的等价性+=被视为赋值运算符,而不是特殊的更新运算符.因此,上面引用的关于"赋值"的文本适用于+=.

  • 这是因为`a + = b`匹配赋值表达式的语法,而不是因为等于`a = a + b`(在重载运算符的情况下甚至不是真的).5.17/7仅涉及非超载情况; 见第5条开头的第3点 (2认同)

das*_*ght 7

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

§8.5.4/ 1 [...]注意:可以使用列表初始化

...

- 在作业的右侧(5.17)

§5.17谈论所有任务,包括复合任务:

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

赋值运算符:一个
= *= /= %= += -= >>= <<= &= ˆ= |=