Can trivial integral const variables always be used as template values?

Viewed 57

This question is similar to this one, but more specific to pre-c++11 scenarios.

I've noticed with Clang and g++ that the following compiles and works fine with pre-c++11:

enum En { V0 = 0 };

template <int SZ> class C { };
template <En EN> class E { };

int main() {
    const int SIZE = 42;
    C<SIZE> c;
    const int SIZE2 = SIZE ^ 0xDEADBEEF;
    C<SIZE2> c2;
    const En E1 = V0;
    E<E1> e1;
}

In a context where no constexpr is available, doing this is incredibly convenient, perhaps even necessary in some cases. So is this guaranteed to work, or are g++ and Clang just inferring these values for convenience?

1 Answers

So is this guaranteed to work

Yes. From [expr.const]/1 in N1905 (which is C++03-ish standard release):

5.19 Constant expressions [expr.const]

/1 In several places, C++ requires expressions that evaluate to an integral or enumeration constant: as array bounds (8.3.4, 5.3.4), as case expressions (6.4.2), as bit-field lengths (9.6), as enumerator initializers (7.2), as static member initializers (9.4.2), and as integral or enumeration non-type template arguments (14.3).

An integral constant-expression can involve only literals of arithmetic types (2.13, 3.9.1), enumerators, non-volatile const variables or static data members of integral or enumeration types initialized with constant expressions (8.5),

Meaning all of the const variables SIZE, SIZE2 and E1 (as these have been initialized with constant expressions) are valid in integral constant-expression, and may thus be used as template arguments for non-type template parameters.

Related