问题
My compiler is the latest VC++ 2013 RC.
int f(bool b)
{
return {}; // OK
return b ? 1 : { }; // C2059: syntax error : '{'
return b ? 1 : {0}; // C2059: syntax error : '{'
return b ? {1} : {0}; // C2059: syntax error : '{'
}
Why can braced-init-list not be used in ternary operator?
Is this behavior defined as ill-formed by the C++ standard, or just a bug of the VC++ compiler?
回答1:
Well, here's what the standard says about the braced-init-list (8.5.3.1):
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 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)
Since this doesn't mention the conditional operator, I guess your compiler is right. Also note that the conditional operator expects expressions on the both sides of :
(5.16), and as far as I understand, a brace-initializer is not an expression.
回答2:
It's a syntax error. A braced-init-list is not an expression, and it doesn't have a type or value category. braced-init-list is available at various locations in the C++ grammar, and the operands of conditional expression are not one of those locations. Therefore your code fails to even parse.
If you want to do this:
struct T { ... };
T f(bool b)
{
return b ? {i,j,k} : {x,y};
}
instead you could do this:
T f(bool b)
{
return b ? T{i,j,k} : T{x,y};
}
and I believe, although this requires a move constructor, it wouldn't use it and RVO would kick in.
Alternatively you could of course do this:
T f(bool b)
{
if (b)
return {i,j,k};
else
return {x,y};
}
to get all the advantages of list-initialization.
来源:https://stackoverflow.com/questions/18843017/why-can-braced-init-list-not-be-used-in-ternary-operator