三元运算符中为啥不能使用braced-init-list?

Posted

技术标签:

【中文标题】三元运算符中为啥不能使用braced-init-list?【英文标题】:Why can braced-init-list not be used in ternary operator?三元运算符中为什么不能使用braced-init-list? 【发布时间】:2013-09-21 11:43:15 【问题描述】:

我的编译器是最新的 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++ 编译器的错误?

【问题讨论】:

不是表达式,这里检查语法Conditional operator differences between C and C++ 据我所知,通过统一初始化应该可以做到return b ? 0 : 1 @Rapptz,返回 b ? 0 : 1 也被拒绝。 @xmllmx 是的,你是对的。它不适用于内置类型。 语法错误是由于?:运算符而不是因为return,所以考虑条件运算符的语法。而表达式是“指定计算的一系列运算符和操作数”(这是 C++ 标准中给出的定义) 【参考方案1】:

嗯,这就是标准对括号初始化列表 (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) 在内存初始化器 (12.6.2) 中 在作业的右侧 (5.17)

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

【讨论】:

【参考方案2】:

这是一个语法错误。大括号初始化列表不是表达式,它没有类型或值类别。括号初始化列表在 C++ 语法中的不同位置可用,条件表达式的操作数不是这些位置之一。因此,您的代码甚至无法解析。

如果你想这样做:

struct T  ... ;

T f(bool b)

    return b ? i,j,k : x,y;

您可以这样做:

T f(bool b)

    return b ? Ti,j,k : Tx,y;

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

当然,您也可以这样做:

T f(bool b)

    if (b)
        return i,j,k;
    else
        return x,y;

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

【讨论】:

如果 T 没有接受这些参数的构造函数,T(i,j,k) 将不起作用。 Ti,j,k 没问题

以上是关于三元运算符中为啥不能使用braced-init-list?的主要内容,如果未能解决你的问题,请参考以下文章

三元运算符中为啥不能使用braced-init-list?

为啥在三元运算符中使用“0”会返回第一个值?

为啥使用三元运算符进行数组初始化是非法的?

如果在三元运算符中使用局部变量,为啥从 int 到 short 的缩小转换不起作用

为啥使用三元运算符返回字符串与在等效 if/else 块中返回的代码有很大不同?

为啥要使用三元运算符而不为“真”条件赋值 (x = x ?: 1)