逗号运算符是否允许在C ++ 11中使用常量表达式?

时间:2013-05-16 00:02:28

标签: c++ c++11 language-lawyer comma-operator constant-expression

在回答C ++ 11 this question on 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中的常量表达式中。

2 个答案:

答案 0 :(得分:14)

  1. 是的,我相信这是C ++ 03和C ++ 11之间的变化。我认为这完全是出于你提到的原因 - 没有特别好的理由,逗号运算符不能成为常量表达式的一部分。

  2. 我认为C ++ 03中的规则源于C中的规则(C90,§6.4):

  3.   

    常量表达式不应包含赋值,递增,递减,函数调用或逗号运算符,除非它们包含在 sizeof 运算符的操作数中。

    为什么在C中的常量表达式中禁止使用逗号运算符,我只能推测。我的直接猜测是确保定义如下:

    int x[2, 5];
    

    ...会被拒绝,而不是让用户错误地认为他已定义了一个2x5元素数组,当(如果允许逗号运算符)时,他确实只定义了x 5个元素。

答案 1 :(得分:3)

  

但是,必须要说的是,即使是以下程序也可以使用-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主干说:

<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语法中的常量表达式是一种条件-expression (不允许使用顶级逗号)。因此:

int arr[0, 42];

仍然是不合格的。