【问题标题】: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++ 标准中给出的定义)

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


【解决方案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 ? T{i,j,k} : T{x,y};
    }
    

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

    当然,您也可以这样做:

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

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

    【讨论】:

    • 如果 T 没有接受这些参数的构造函数,T(i,j,k) 将不起作用。 T{i,j,k} 没问题
    猜你喜欢
    • 1970-01-01
    • 2022-12-22
    • 1970-01-01
    • 2013-07-30
    • 2014-11-29
    • 1970-01-01
    • 2015-10-07
    • 2018-03-16
    • 2016-05-15
    相关资源
    最近更新 更多