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(除了编译器警告说逗号运算符没有效果且x和arr变量未使用):
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
是的,我相信这是C++ 03和C++ 11之间的变化.我相信它是基于你提到的原因 - 只是没有特别好的理由,逗号运算符不能成为常量表达式的一部分.
我相信C++ 03中的规则源于C中的规则(C90,§6.4):
常量表达式不应包含赋值,递增,递减,函数调用或逗号运算符,除非它们包含在sizeof运算符的操作数中.
至于为什么在C中的常量表达式中禁止使用逗号运算符,我只能推测.我的直接猜测是确保定义如下:
int x[5, 2];
Run Code Online (Sandbox Code Playgroud)
...会被拒绝,而不是让用户错误地认为他已经定义了一个2x5元素数组,当(如果允许逗号运算符)时,他实际上x只定义了5个元素.
\n\n\n然而,必须说的是,即使使用 -std=c++03 选项(在 Clang 和 GCC 上),以下程序也能正常编译,考虑到上面引用的 C++03 标准,这显然是不正确的
\n
没那么快。您还需要使用-pedantic(或-pedantic-errors) 让 Clang 和 GCC 严格执行 C++03 规则。GCC 主干说:
<stdin>:1:16: error: array bound is not an integer constant before \xe2\x80\x98]\xe2\x80\x99 token\nRun Code Online (Sandbox Code Playgroud)\n\nClang 树干说:
\n\n<stdin>:1:19: error: variable length arrays are a C99 feature [-Werror,-Wvla-extension]\nvoid f() { int arr[(0, 42)]; }\n ^\nRun Code Online (Sandbox Code Playgroud)\n\n正如您所注意到的,此代码是有效的 C++11。但是,顶级逗号在 C++11 中仍然无效,因为C++11 语法中的常量表达式是一种条件表达式(不允许使用顶级逗号)。因此:
\n\nint arr[0, 42];\nRun Code Online (Sandbox Code Playgroud)\n\n仍然是不正确的。
\n