It has to be a integral constant expression. That's explained by the Standard document at 5.19
:
An integral constant-expression can involve only literals (2.13), enumerators, const variables or static data members of integral or enumeration types initialized with constant expressions (8.5), non-type template parameters of integral or enumeration types, and sizeof expressions. Floating literals (2.13.3) can appear only if they are cast to integral or enumeration types. Only type conversions to integral or enumeration types can be used.
Note that "integral" is another term for "integer", but is not the same as "int". "char" for example has integer/integral type, but is not the int type, obviously. So concretely, the following is allowed
10 or 10L or anything like that
enum { THIS, OR, THAT };
int const this_one = 10;
sizeof(char)
- of course, any other template parameter as detailed above
Any of those can be used as a template argument for a parameter that has an integral type of the corresponding type. Some conversions are still applied though. So if it wants an int and you pass a char, it automatically promotes the char to the int. Same if you provide an enumerator and it wants an int.
So by those rules, if you have
extern const int SomeName;
And it does not see a definition which initializes that constant with a integral constant expression, it can't be used as a template argument. But it can be used as a function argument, of course. Those don't need to be known at compile time because those are not part of a type. The moment you name a template specialization, the arguments you used become part of the type:
MyGreatStack<int, 4> // 4 is now part of the type MyGreatStack<int, 4>!
Note that there are other ways to pass SomeName
as an argument. However, all of which can not be accepted by an integer template parameter. You can accept the above by a reference parameter, for example
template<const int& V> struct NowItWorks { };
And it would accept the SomeName
of above. Now, rather than a value, a particular location that is unique across the whole program (as the variable has extern
linkage) has been chosen.