32

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?

xmllmx
  • 39,765
  • 26
  • 162
  • 323
  • 3
    `{}` is not an expression, check grammar here [Conditional operator differences between `C` and `C++`](http://stackoverflow.com/a/1082680/1673391) – Grijesh Chauhan Sep 17 '13 at 06:49
  • 1
    With uniform initialization it should be possible to do `return b ? {0} : {1}` as far as I know. – Rapptz Sep 17 '13 at 06:50
  • @Rapptz, return b ? {0} : {1} is also rejected. – xmllmx Sep 17 '13 at 06:52
  • @xmllmx Yeah, you're right. It doesn't work with built-in types. – Rapptz Sep 17 '13 at 06:55
  • Syntax error is due to `?:` operator but not because of `return`, so consider grammar of Conditional operator. And An expression is "a sequence of operators and operands that specifies a computation" (that's the definition given in the C++ standard) – Grijesh Chauhan Sep 17 '13 at 06:58

2 Answers2

21

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.

SingerOfTheFall
  • 29,228
  • 8
  • 68
  • 105
8

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.

Andrew Tomazos
  • 66,139
  • 40
  • 186
  • 319