【问题标题】:Why can braced-init-list not be used in ternary operator?为什么braced-init-list不能用在三元运算符中?
【发布时间】:2022-12-22 19:35:31
【问题描述】:

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

好吧,这是标准对 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)
  • 在内存初始化器 (12.6.2) 中
  • 在作业的右侧 (5.17)

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

【讨论】:

    【解决方案2】:

    这是一个语法错误。 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};
    }
    

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

    【讨论】:

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