Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

c++11

The following code uses enum member m as a constant expression, i.e. as a template parameter. The code compiles under gcc but not under clang (live demo). Clang says "error: non-type template argument is not a constant expression".

The problem can be solved by exchanging line // 1 by A<tst<p>::m> a. Therefore, my question is not how to fix this issue 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
    }
};
like image 438
Claas Bontus Avatar asked Jul 15 '16 14:07

Claas Bontus


People also ask

Is it better to use enum or constant?

Enums are lists of constants. When you need a predefined list of values which do represent some kind of numeric or textual data, you should use an enum. You should always use enums when a variable (especially a method parameter) can only take one out of a small set of possible values.

Are enums compile time?

Enum values or Enum instances are public, static, and final in Java. They are a compile-time constant, which means you can not changes values of Enum instances and further assignment will result in a compile-time error.

Are enums constants C++?

An enumeration is a user-defined type that consists of a set of named integral constants that are known as enumerators. This article covers the ISO Standard C++ Language enum type and the scoped (or strongly-typed) enum class type which is introduced in C++11.

Can an enum be const?

A const Enum is the same as a normal Enum. Except that no Object is generated at compile time. Instead, the literal values are substituted where the const Enum is used.


1 Answers

According to the Standard, Clang is right to reject the code.

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

[...] The postfix expression before the dot or arrow is evaluated; the result of that evaluation, together with the id-expression, determines the result of the entire postfix expression.

There's also a note:

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

So, the subexpression t2 is evaluated. [expr.const]/2.9 says that an expression e cannot be a core constant expression if evaluating it results in the evaluation of

an id-expression that refers to a variable or data member of reference type unless the reference has a preceding initialization and either

  • it is initialized with a constant expression or
  • its lifetime began within the evaluation of e;

t2 refers to a variable of reference type that doesn't satisfy the bullets, so t2.m is not a constant expression because it isn't a core constant expression.


All quotes from N4594, the current published working draft. The text has changed slightly since C++11, but the meaning in this case is the same.

like image 128
bogdan Avatar answered Nov 06 '22 23:11

bogdan