Why Was the Restriction on the Comma Operator Being in a Constant Expression Removed in C++11

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

  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.

comma operator makes lambda expression non-constexpr

Its seems to be a clang bug, according to [basic.def.odr]/4:

A variable x whose name appears as a potentially-evaluated expression ex is odr-used by ex unless applying the lvalue-to-rvalue conversion (7.1) to x yields a constant expression (8.20) that does not invoke any non-trivial functions and, if x is an object, ex is an element of the set of potential results of an expression e, where either the lvalue-to-rvalue conversion (7.1) is applied to e, or e is a discarded-value expression.

As has been commented, the issue is not limited to the comma operator but for every discarded expressions, these expression doesn't constitute odr-use, hence it must be accepted.

Evaluation order in parenthesis and comma expression in C++ of the type (x0 = y0, x1 = y1, x2 = x0, ...)

First, what is the name in the language (and link on cppreference) to this "parenthesis" expression where only the last term is returned;

"comma operator".

I mean: the comma operator evaluate but discard the element on the left and return the element on the right (if the element on the left isn't an object with comma operator redefined).

And there is no need of parenthesis; you can also write.

return a, b, c, d;

Second, let's say the code becomes [...] Is the order of evaluation of theses "parenthesis" expressions fixed?

Yes; from left to right.

Look for "sequence point" for more info.

And from

return a += 2, d += 5, b -= 3, c = a + b + d, d;

you get exactly the same result that you get from

a += 2; d += 5; b -= 3; c = a + b + d; return d;

taking also in count that a, d, b and c are ints and that int isn't a class that redefine the comma operator.

But do not confuse the comma in "comma operator" with the comma that separate the arguments in a function calling. The first one is a "sequence point", the second one isn't.

I mean: with

int i = 0;

return i++, i++, i++;

the returned value is defined (2); if foo() is a function that receive three integers, with

int i = 0;

foo(i++, i++, i++);

you know that foo() receive a zero, a one and a two but the order is unspecified (can be 0 for the first parameter and 2 for the third or the contrary).

Finally, purely in C++11 [...] can this parentheses expressions be used to write several computation in a single constexpr function?

Yes.

And (IMHO) it's a very useful feature.

In the comma operator, is the left operand guaranteed not to be actually executed if it hasn't side effects?

The comma operator (C documentation, says something very similar) has no such guarantees.

In a comma expression E1, E2, the expression E1 is evaluated, its result is discarded ..., and its side effects are completed before evaluation of the expression E2 begins

irrelevant information omitted

To put it simply, E1 will be evaluated, although the compiler might optimize it away by the as-if rule if it is able to determine that there are no side-effects.

Is it good practice to use the comma operator?

It can be useful in the condition of while() loops:

while (update_thing(&foo), foo != 0) {
/* ... */
}

This avoids having to duplicate the update_thing() line while still maintaining the exit condition within the while() controlling expression, where you expect to find it. It also plays nicely with continue;.

It's also useful in writing complex macros that evaluate to a value.

Is difference between two pointers legal c++17 constant expression?

The question is moot. Pointer arithmetics is only defined on the pointers belonging to the same array, which is certainly not the case there. So, the code above is not legal C++, and in fact, fails to compile with compilers available to me.

postincrement operation in same statement

In this case, since the "comma separated expressions" are parameters of a function (strlcpy), the order of evaluation of the expressions is unspecified, even in C++17.
However, C++17 guarantees that expression evaluation won't be interleaved between arguments, so that each expression is fully formed before forming another one.
So, in your strlcpy(&a[i++],"Text",SZ-i), you cannot rely on the value of i: it could exhibit a different behavior depending on your implementation. Though since it's not undefined behavior, you know it's either going to be the old value of i, or the old value plus one.

C++ Array Definition with Lower and Upper Bound?

This is not valid, from the draft C++ standard section 8.3.4 Arrays the declaration must be of this form:

D1 [ constant-expressionopt] attribute-specifier-seqopt

and we can from section 5.19 Constant expressions the grammar for constant expression is:

constant-expression:
conditional-expression

This grammar does not allow us to get to the comma operator either to do something like this:

int a[ 1, 2 ] ;
^

as others have implied since there is no path to comma operator from conditional-expression. Although if you add parenthesis we can get to the comma operator since conditional-expression allows us to get to primary-expression which gets us () so the following would be valid:

int a[ (1, 2) ] ;
^ ^

Note, in C++03 you were explicitly forbidden from using the comma operator in a constant expression.



Related Topics



Leave a reply



Submit