Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can I use operator= but not operator== with C++11 brace-initializers?

Tags:

c++

c++11

See this example:

struct Foo
{
    int a;
    int b;

    bool operator == (const Foo & x)
    {
        return a == x.a && b == x.b;
    }
};

int main ()
{
    Foo a;

    a = {1, 2};

    if (a == {1, 2}) // error: expected primary-expression before ‘{’ token
    {
    }
}

The line a={1,2} is fine. The braces are convert to a Foo to match the argument type of the implicit operator= method. It still works if operator= is user-defined.

The line if (a=={1,2}}) errors as indicated.

Why does the expression {1,2} not convert to a Foo to match the user-defined operator== method?

like image 228
spraff Avatar asked Apr 23 '13 12:04

spraff


3 Answers

List-initialization cannot be used as an argument to an operator in the general case. Per Paragraph 8.5.4/1 of the C++11 Standard:

[...] List-initialization can be used

— as the initializer in a variable definition (8.5)

— as the initializer in a new expression (5.3.4)

— in a return statement (6.6.3)

— as a for-range-initializer (6.5)

as a function argument (5.2.2)

— as a subscript (5.2.1)

— as an argument to a constructor invocation (8.5, 5.2.3)

— as an initializer for a non-static data member (9.2)

— in a mem-initializer (12.6.2)

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

The last item explains why list-initialization is allowed on the right side of operator =, even though it is not allowed in general for an arbitrary operator.

Because of the fifth item above, however, it can be used as an argument to a regular function call, this way:

if (a.operator == ({1, 2}))
like image 170
Andy Prowl Avatar answered Nov 09 '22 17:11

Andy Prowl


It's just simply not supported.

Initializer lists are explicitly defined to be valid in initializations ([C++11: 8.5.4]), and assignments:

[C++11: 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) except that no narrowing conversion (8.5.4) is allowed. The meaning of x={} is x=T().
  • an assignment defined by a user-defined assignment operator, in which case the initializer list is passed as the argument to the operator function.

There is no standard wording to allow other, arbitrary cases.

If it were allowed, in this example, the type of {1,2} would be fairly ambiguous. It would be a complicated language feature to implement.

like image 29
Lightness Races in Orbit Avatar answered Nov 09 '22 15:11

Lightness Races in Orbit


An explicit cast is required.

if (a == (Foo){1, 2})
{
}
like image 4
johnchen902 Avatar answered Nov 09 '22 17:11

johnchen902