c++ 11中常量表达式中是否允许使用逗号操作符?



在c++ 11的SO上回答这个问题的过程中,我意识到在c++ 03中(以及在C中),在常量表达式中明确禁止使用逗号操作符。

c++ 03标准关于常量表达式的第5.19/1段说:

[…特别地,除了sizeof表达式、函数、类对象、指针或不能使用引用,赋值、自增、自减、函数调用或逗号操作符.

然而,在c++ 11中,最后提到逗号操作符的部分似乎消失了。尽管c++ 11标准第5.19/2段明确规定,赋值、自增、自减和非constexpr函数调用表达式不得作为常量表达式的子表达式出现,但逗号操作符的使用似乎不再被禁止了。

例如,下面的程序在GCC 4.7.2和Clang 3.3中使用std=c++11可以很好地编译(除了编译器警告说逗号操作符不起作用并且xarr变量未被使用):

int main()
{
    constexpr int x = (0, 42);
    int arr[(0, 42)];
}
然而,必须指出的是,即使下面的程序使用-std=c++03选项(Clang和GCC)也可以很好地编译,这显然是正确的,因为上面引用了c++ 03标准:
int main()
{
    int arr[(0, 42)];
}

问题:

是否有c++ 03和c++ 11之间的差异,是否允许在常量表达式中使用逗号操作符,或者我错过了什么?

作为一个额外的(非建设性的)问题,我想知道为什么在c++ 03中不能在常量表达式中使用逗号操作符。

  1. 是的,我相信这是c++ 03和c++ 11之间的变化。我相信这样做的原因大致与您提到的原因相同——逗号操作符不能作为常量表达式的一部分并没有特别好的理由。

  2. 我相信c++ 03中的规则起源于C (C90,§6.4)中的规则:

常量表达式不得包含赋值、自增、自减、函数调用或逗号操作符,除非这些操作符包含在sizeof操作数内。

关于C中常量表达式为什么禁止逗号操作符,我只能推测。我的直接猜测是确保像

这样的定义
int x[5, 2];

…会被拒绝。如果允许,它可能会导致程序员错误地认为他定义了一个5x2元素的数组(总共10个元素),而(如果这里允许逗号操作符)他实际上只定义了2个元素的x(并且5实际上被完全忽略了)。

至于为什么c++委员会认为这是比C委员会更可接受的风险,我猜这可以归结为一个相当简单的情况:C几乎没有提供任何替代方案,因此数组使用得相当多。另一方面,c++同时提供了std::arraystd::vector,因此很少有理由使用"原始"数组的情况,因此问题不太可能出现。

然而,必须指出的是,即使下面的程序使用-std=c++03选项(在Clang和GCC上)也能很好地编译,这显然是不正确的,因为上面引用了c++03标准

别那么快。您还需要使用-pedantic(或-pedantic-errors)来使Clang和GCC严格执行c++ 03规则。这样,GCC主干说:

<stdin>:1:16: error: array bound is not an integer constant before ‘]’ token

和Clang trunk说:

<stdin>:1:19: error: variable length arrays are a C99 feature [-Werror,-Wvla-extension]
void f() { int arr[(0, 42)]; }
                  ^

正如您注意到的,这段代码是有效的c++ 11。然而,在c++ 11中,顶层的逗号仍然是无效的,因为c++ 11语法中的常量表达式是一种条件表达式(顶层的逗号是不允许的)。因此:

int arr[0, 42];

相关内容

  • 没有找到相关文章