Using an enumeration as a constant expression. Which compiler is right?

The following code uses the enum m element as a constant expression, that is, as a template parameter. The code compiles under gcc, but not under clang ( live demo ). Klang says: "Error: the non-piggy type template argument is not a constant expression."

The problem can be solved by exchanging the string // 1 with A<tst<p>::m> a . So my question is not how to fix this problem, but which compiler is right.

 template<size_t n> struct A{}; template<size_t n> struct tst { enum : size_t { m= n % 15 }; template<size_t p> void call( tst<p> const &t2 ) { A<t2.m> a; // 1 } }; 
+6
c ++ c ++ 11
source share
1 answer

According to the standard, Clang has the right to reject the code.

t2.m is an expression to access a member of a class. [expr.ref] / 1 says:

[...] A postfix expression is expressed before a point or arrow; the result of this evaluation, together with the id-expression, determines the result of the entire postfix expression.

There is also a note:

If an access expression to a member of a class is evaluated, a subexpression is evaluated even if the result is not necessary to determine the value of the entire postfix expression, for example, if id-expression denotes a static member.

So, the subexpression t2 is estimated. [expr.const] /2.9 says that the expression e cannot be the main constant expression if its evaluation leads to the evaluation

An id expression that refers to a variable or link data item type if the link does not have a previous initialization and either

  • it is initialized with a constant expression or
  • his lifetime began with an estimate of e ;

t2 refers to a variable of a reference type that does not satisfy bullets, so t2.m not a constant expression, because it is not the main expression of a constant.


All citations from N4594, current published working draft. The text has changed a bit since C ++ 11, but the point is the same.

+3
source share

All Articles