C ++ 11中的常量表达式中是不是允许逗号运算符?
Posted
技术标签:
【中文标题】C ++ 11中的常量表达式中是不是允许逗号运算符?【英文标题】:Is the comma operator allowed in a constant-expression in C++11?C ++ 11中的常量表达式中是否允许逗号运算符? 【发布时间】:2013-05-10 17:26:06 【问题描述】:在为 C++11 回答 this question on SO 的过程中,我意识到在 C++03(以及 C)中,在 constant-expression。
C++03 标准关于常量表达式的第 5.19/1 段说:
[...] 特别是,除了 sizeof 表达式、函数、类对象、指针或 不应使用引用,并且应使用赋值、递增、递减、函数调用或 逗号运算符 不能使用。
然而,在 C++11 中,最后提到逗号运算符的部分似乎消失了。虽然 C++11 标准的第 5.19/2 段明确规定赋值、递增、递减和非constexpr
函数调用表达式不得作为 constant-expression 的子表达式出现, 逗号运算符的使用似乎不再被禁止了。
例如,以下程序在 GCC 4.7.2 和 Clang 3.3 上使用 std=c++11
编译良好(除了编译器警告说逗号运算符无效并且 x
和 arr
变量未使用):
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 之间的变化。我相信这样做的大致原因是您提到的 - 没有特别好的理由逗号运算符不能成为常量表达式的一部分。
我相信 C++03 中的规则源自 C 中的规则(C90,§6.4):
常量表达式不应包含赋值、递增、递减、函数调用或逗号运算符,除非它们包含在 sizeof 运算符的操作数中。
至于为什么C语言的常量表达式中禁止使用逗号,我只能推测。我的直接猜测是确保如下定义:
int x[5, 2];
...将被拒绝。如果它被允许,它可能会导致程序员错误地认为他定义了一个 5x2 元素数组(总共 10 个元素),而(如果在那里允许逗号运算符)他真的定义了 x
只有 2 个元素(5
被完全忽略)。
至于为什么 C++ 委员会认为这是一个比 C 委员会更容易接受的风险,我想这归结为一个相当简单的情况:C 几乎没有提供替代方案,因此使用了相当多的数组。另一方面,C++ 同时提供了std::array
和std::vector
,在极少数情况下有很多理由使用“原始”数组,因此问题出现的可能性要小得多。
【讨论】:
【参考方案2】:但是,必须说即使以下程序也可以使用 -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。但是,top-level 逗号在 C++11 中仍然无效,因为 C++11 语法中的 constant-expression 是一种 conditional -expression(不允许使用***逗号)。因此:
int arr[0, 42];
仍然不正确。
【讨论】:
以上是关于C ++ 11中的常量表达式中是不是允许逗号运算符?的主要内容,如果未能解决你的问题,请参考以下文章