为什么braced-init-list不能用于三元运算符?

时间:2013-09-17 06:47:10

标签: c++ visual-c++ c++11 initialization ternary-operator

我的编译器是最新的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 : '{'
}

为什么braced-init-list不能用于三元运算符?

这种行为是否被C ++标准定义为不正确,或者仅仅是VC ++编译器的错误?

2 个答案:

答案 0 :(得分:19)

嗯,这是标准关于braced-init-list(8.5.3.1)的内容:

  

列表的初始化   可以使用

     
      
  • 作为变量定义中的初始化程序(8.5)
  •   
  • 作为新表达式(5.3.4)
  • 中的初始值设定项   
  • 在退货声明(6.6.3)
  • 中   
  • 作为函数参数(5.2.2)
  •   
  • 作为下标(5.2.1)
  •   
  • 作为构造函数调用的参数(8.5,5.2.3)
  •   
  • 作为非静态数据成员的初始化程序(9.2)
  •   
  • 在mem-initializer(12.6.2)
  • 中   
  • 位于作业的右侧(5.17)
  •   

由于这没有提到条件运算符,我猜你的编译器是对的。另请注意,条件运算符需要:(5.16)两边的表达式,据我所知,大括号初始化器不是表达式。

答案 1 :(得分:7)

这是一个语法错误。 braced-init-list不是表达式,它没有类型或值类别。 braced-init-list在C ++语法的各个位置都可用,并且条件表达式的操作数不是这些位置之一。因此,您的代码甚至无法解析。

如果你想这样做:

struct T { ... };

T f(bool b)
{
    return b ? {i,j,k} : {x,y};
}

相反,你可以这样做:

T f(bool b)
{
    return b ? T{i,j,k} : T{x,y};
}

我相信,虽然这需要一个移动构造函数,但它不会使用它而RVO会启动。

或者你当然可以这样做:

T f(bool b)
{
    if (b)
        return {i,j,k};
    else
        return {x,y};
}

获得列表初始化的所有优点。