23

在回答关于 C++11的 SO 的这个问题的过程中,我意识到在 C++03(以及 C 中)中,在constant-expression中明确禁止使用逗号运算符。

C++03 Standard 关于常量表达式的第 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 中的常量表达式。

4

2 回答 2

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

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

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

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

int x[5, 2];

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

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

于 2013-05-16T02:54:10.410 回答
4

但是,必须说,即使是以下程序也可以使用 -std=c++03 选项(在 Clang 和 GCC 上)编译良好,这显然是不正确的,因为上面引用了 C++03 标准

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

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

和铿锵的树干说:

<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];

仍然是不正确的。

于 2013-07-14T00:31:24.483 回答