Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top