Why are some non-constant expressions allowed as operands of a constexpr comma operator?

  • A+

Consider a simple example:

int foo() {     return 3; }  template <int> struct Bar {};  int a;  int main() {     int b;     //Bar<((void)foo(), 1)> bar1;  //case 1. compilation error as expected     Bar<((void)a, 2)> bar2;        //case 2. no error (long shot but `a' has a linkage so maybe expected)     Bar<((void)b, 3)> bar3;        //case 3. no error ? (`b' does not have linkage)      (void)bar2;     (void)bar3; } 

I would say it is a bug but both the latest [clang] and [gcc] accept the code so maybe I'm missing some relevant standard rule that makes the code valid?


The lvalue-to-rvalue conversion is not applied to the first argument of the comma operator unless it is volatile. Therefore, (void)a, 2 and (void)b, 3 are constant expressions.

See [expr.comma]/1

... the left expression is a discarded-value expression ...

and [expr]/12

... The lvalue-to-rvalue conversion is applied [to a discarded-value expression] if and only if the expression is a glvalue of volatile-qualified type and it is one of the following: ...


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: