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?
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}))
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}
, whereT
is the scalar type of the expressionx
, is that ofx=T(v)
except that no narrowing conversion (8.5.4) is allowed. The meaning ofx={}
isx=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.
An explicit cast is required.
if (a == (Foo){1, 2})
{
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With