Even if you already accepted @iammilind's answer, let me suggest one more, because his argument as to why i not a constant of the compile-time constant is not true.
Suppose you have
template<unsigned int MAX> struct SubDomain {...}; ...
and you want to declare an instance of it ...
SubDomain<i> tmp(member);
then i should usually be the so-called compile-time constant. What is it?
Pedantry
The standard assigns the term nontype template argument that are not types (D'Oh).
14.3.2 Non-type argument templates [temp.arg.nontype]
The template argument for a non-piggy template without template must be one of:
- integral constant expression of an integral or enumerated type; or
-... [further followed, but not relevant]
To the right, the first dot contains a link for further research: an integral constant-expression . It brings us to
5.19 Constant Expressions [expr.const]
In several places, C ++ requires expressions that calculate an integral or continuous constant: as an array (8.3.4, 5.3.4), as expressions in the case of (6.4.2), as the length of bit fields (9.6), as initializers of the enumerator (7.2), as initializers of static elements (9.4.2), and as integral or enumerated arguments of a non-piggy type template (14.3) .
Then the key:
An integral constant expression can include only literals (2.13), counters, constant variables or static data members of integral or enumerated types, initialized by constant expressions (8.5), a non-type type template, parameters of integral or enumerated types, and sizeof expressions.
Pedantry application
If we look back at your cycle:
for (int i=... ... SubDomain<i>
then now we can notice that i is not allowed there. What for? Since i NOT a const variable .
Now the observer might think that you can get around this:
for (int i=... ... const int I = i; SubDomain<I>
But is it really allowed? Negative, I = i not an integral constant expression, because i not. This helps to understand that the rule for integral constant expressions is applied recursively.
For example, suppose the following code:
template <int> void foo() {} int main () { const int ccI = 0; const int ccJ = ccI*2; const int ccK = ccJ/4; foo<ccK>(); }
But if only one part of the chain is made not const, then ccK no longer considered an integral constant:
template <int> void foo() {} int main () { int ccI = 0; const int ccJ = ccI*2;
Summary
Thus, in a human-readable form, template arguments that are not types but (integer) values ββmust be compilation constants:
- The compile-time constant initializer should include only other compile-time constants
- literal value - compile time constant
- enum value is a compile time constant
- Functional calls do not give compile-time constants (for some preliminary reasons)