Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the comma operator allowed in a constant-expression in C++11?

Tags:

In the process of answering this question on SO for C++11, I realized that in C++03 (as well as in C) the use of the comma operator is explicitly forbidden in a constant-expression.

Paragraph 5.19/1 of the C++03 Standard on constant expressions says:

[...] In particular, except in sizeof expressions, functions, class objects, pointers, or references shall not be used, and assignment, increment, decrement, function-call, or comma operators shall not be used.

In C++11, however, that last part mentioning the comma operator seems to be vanished. And while paragraph 5.19/2 of the C++11 Standard clearly specifies that assignment, increment, decrement, and non-constexpr function call expressions shall not appear as sub-expressions of a constant-expression, the usage of the comma operator does not seem to be forbidden anymore.

For instance, the following program compiles fine on GCC 4.7.2 and Clang 3.3 with std=c++11 (apart from compiler warnings saying the comma operator has no effect and the x and arr variables are unused):

int main() {     constexpr int x = (0, 42);     int arr[(0, 42)]; } 

However, it must be said that even the following program compiles fine with the -std=c++03 option (both on Clang and GCC), which is clearly not correct, given the above quote from the C++03 Standard:

int main() {     int arr[(0, 42)]; } 

QUESTION:

Is there a difference between C++03 and C++11 as to whether or not the comma operator is allowed in a constant expression, or am I missing something?

As a bonus (non-constructive) question, I would be interested in knowing why the comma operator cannot be used in a constant expression in C++03.

like image 953
Andy Prowl Avatar asked May 16 '13 00:05

Andy Prowl


People also ask

Where do we use comma operator in C?

The comma operator in c comes with the lowest precedence in the C language. The comma operator is basically a binary operator that initially operates the first available operand, discards the obtained result from it, evaluates the operands present after this, and then returns the result/value accordingly.

Can we use comma in for loop in C?

The comma operator will always yield the last value in the comma separated list. Basically it's a binary operator that evaluates the left hand value but discards it, then evaluates the right hand value and returns it. If you chain multiple of these they will eventually yield the last value in the chain.

What is a constant expression in C?

A constant expression gets evaluated at compile time, not run time, and can be used in any place that a constant can be used. The constant expression must evaluate to a constant that is in the range of representable values for that type.

Is comma a special character in C?

In C and C++, comma (, ) can be used in two contexts: 1) Comma as an operator: The comma operator (represented by the token, ) is a binary operator that evaluates its first operand and discards the result, it then evaluates the second operand and returns this value (and type).


2 Answers

  1. Yes, I believe this is a change between C++03 and C++11. I believe it was done for roughly the reason to which you allude -- that there's no particularly good reason a comma operator can't be part of a constant expression.

  2. I believe the rule in C++03 originated from the rule in C (C90, §6.4):

Constant expressions shall not contain assignment, increment, decrement, function-call, or comma operators, except when they are contained within the operand of a sizeof operator.

As to why the comma operator was prohibited in constant expressions in C, I can only speculate. My immediate guess would be to assure that a definition like:

int x[5, 2]; 

...would be rejected. If it were allowed, it could lead the programmer to the mistaken belief that he'd defined a 5x2 element array (for a total of 10 elements), when (if a comma operator were allowed there) he'd really defined x with only 2 elements (and the 5 was effectively ignored completely).

As to why the C++ committee considered this a more acceptable risk than the C committee, I'd guess it comes down to a fairly simple situation: C provides nearly no alternative, so arrays are used quite a bit. C++, on the other hand, provides both std::array and std::vector, leaving extremely few situations in which there's much reason to use a "raw" array, so the problem is a lot less likely to arise.

like image 121
Jerry Coffin Avatar answered Sep 17 '22 15:09

Jerry Coffin


However, it must be said that even the following program compiles fine with the -std=c++03 option (both on Clang and GCC), which is clearly not correct, given the above quote from the C++03 Standard

Not so fast. You need to also use -pedantic (or -pedantic-errors) to get Clang and GCC to strictly enforce the C++03 rules. With that, GCC trunk says:

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

and Clang trunk says:

<stdin>:1:19: error: variable length arrays are a C99 feature [-Werror,-Wvla-extension] void f() { int arr[(0, 42)]; }                   ^ 

As you note, this code is valid C++11. However, top-level commas are still not valid in C++11, because a constant-expression in the C++11 grammar is a kind of conditional-expression (where a top-level comma is not permitted). Thus:

int arr[0, 42]; 

is still ill-formed.

like image 22
Richard Smith Avatar answered Sep 21 '22 15:09

Richard Smith