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

And*_*owl 23 c++ comma-operator language-lawyer constant-expression 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)];
}
Run Code Online (Sandbox Code Playgroud)

但是,必须要说的是,即使是以下程序也可以使用-std=c++03选项(在Clang和GCC上)编译好,这显然是正确的,考虑到C++ 03标准的上述引用:

int main()
{
    int arr[(0, 42)];
}
Run Code Online (Sandbox Code Playgroud)

题:

关于逗号运算符是否允许在常量表达式中,或者我是否遗漏了某些内容,C++ 03和C++ 11之间是否存在差异?

作为一个奖励(非建设性)问题,我有兴趣知道为什么逗号运算符不能用在C++ 03中的常量表达式中.

Jer*_*fin 15

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

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

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

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

int x[5, 2];
Run Code Online (Sandbox Code Playgroud)

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


Ric*_*ith 5

\n

然而,必须说的是,即使使用 -std=c++03 选项(在 Clang 和 GCC 上),以下程序也能正常编译,考虑到上面引用的 C++03 标准,这显然是不正确的

\n
\n\n

没那么快。您还需要使用-pedantic(或-pedantic-errors) 让 Clang 和 GCC 严格执行 C++03 规则。GCC 主干说:

\n\n
<stdin>:1:16: error: array bound is not an integer constant before \xe2\x80\x98]\xe2\x80\x99 token\n
Run Code Online (Sandbox Code Playgroud)\n\n

Clang 树干说:

\n\n
<stdin>:1:19: error: variable length arrays are a C99 feature [-Werror,-Wvla-extension]\nvoid f() { int arr[(0, 42)]; }\n                  ^\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n
int arr[0, 42];\n
Run Code Online (Sandbox Code Playgroud)\n\n

仍然是不正确的。

\n