Даже если вы уже приняли ответ @iammilind, позвольте мне предложить другой, потому что его аргументация о том, почему i
не является постоянной во время компиляции , является , была неправильной.
Предположим, у вас есть
template<unsigned int MAX> struct SubDomain {...};
...
и вы хотите объявить его экземпляр ...
SubDomain<i> tmp(member);
, тогда i
должен быть обычно так называемой компиляцией-время постоянной .Что это?
Pedantry
Стандарт присваивает термин nontype template argument
аргументам шаблона, которые не являются типами (D'Oh).
14.3.2 Аргументы не типового шаблона [temp.arg.nontype]
Аргумент шаблона для нетип, не шаблонный шаблон-параметр должен быть одним из:- интегральная константа-выражение целочисленного или перечислительного типа;или же- ... [подробнее следите, но не актуально]
Справа первый пункт содержит ссылку для дальнейших исследований: an integral constant-expression
.Это приводит нас к
5.19 Постоянным выражениям [expr.const]
В некоторых местах C ++ требует выражений, которые оцениваютк интегралу или константе перечисления: как границы массива (8.3.4, 5.3.4), как выражения регистра (6.4.2), как длины битового поля (9.6), как инициализаторы перечислителя (7.2), как инициализаторы статических членов (9.4.2), и в качестве целочисленных или перечисляемых нетиповых аргументов шаблонного типа (14.3) .
Тогда ключ:
Интегральное выражение-константа может включать только литералы (2.13), перечислители, константные переменные или члены-статические данные целочисленных или перечислимых типов, инициализированных константными выражениями (8.5), нетипизированные параметры шаблона целочисленного или перечислительного типов,и размер выражений.
Приложение Pedantry
Если мы оглянемся на ваш цикл:
for (int i=...
...
SubDomain<i>
, то теперь мы можем заметить, что i
там не разрешено.Зачем?Потому что i
НЕ является const variable
.
Читатель-наблюдатель может подумать, что вы можете обойти это:
for (int i=...
...
const int I = i;
SubDomain<I>
Но действительно ли это разрешено?Отрицательное, I = i
не является целочисленным константным выражением , потому что i
- нет.Это помогает понять, что правило для интегральных константных выражений применяется рекурсивно.
Например, допустим следующий код:
template <int> void foo() {}
int main () {
const int ccI = 0;
const int ccJ = ccI*2;
const int ccK = ccJ/4;
foo<ccK>();
}
Но если сделать только одну часть цепочки неconst, то ccK
больше не считается интегральной константой:
template <int> void foo() {}
int main () {
int ccI = 0;
const int ccJ = ccI*2; // not compile time constant
const int ccK = ccJ/4; // same
foo<ccK>(); // error
}
Сводка
Таким образом, в удобочитаемой для человека форме аргументы шаблона, которые являются не типами, а (целочисленными) значениями, должны быть постоянными времени компиляции:
- инициализатор постоянной времени компиляции должен включать только другие постоянные времени компиляции
- литеральное значение является постоянной времени компиляции
- значение перечисления является постоянной времени компиляции
- вызовы функций не дают постоянных времени компиляции (по некоторым сложным причинам)