Несмотря на то, что вы уже приняли ответ @iammilind, позвольте мне предложить еще один, потому что его рассуждения о том, почему i
не является константой времени компиляции is, были неверными.
Предположим, у вас есть
template<unsigned int MAX> struct SubDomain {...};
...
и вы хотите объявить его экземпляр...
SubDomain<i> tmp(member);
тогда i
должно быть так называемой константой времени компиляции. Что это?
Педантичность
Стандарт присваивает термин 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), в качестве выражения case (6.4.2), в качестве длины битового поля (9.6), в качестве инициализаторы перечислителя (7.2), как инициализаторы статических членов (9.4.2), и как целочисленные или перечисляемые аргументы нетипового шаблона (14.3).
Тогда ключ:
Интегральное выражение-константа может включать только литералы (2.13), перечислители, константные переменные или статические элементы данных целочисленного или перечисляемого типов, инициализированные константными выражениями (8.5), нетиповые параметры шаблона целочисленного или перечисляемого типов и выражения sizeof.
Применение педантизма
Если мы оглянемся на ваш цикл:
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>();
}
Но если хотя бы одну часть цепочки сделать непостоянной, то 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
}
Резюме
Итак, в удобочитаемой форме аргументы шаблона, которые не являются типами, а (целочисленными) значениями, должны быть постоянными во время компиляции:
- инициализатор константы времени компиляции должен включать только другие константы времени компиляции
- буквальное значение является константой времени компиляции
- значение перечисления является константой времени компиляции
- функциональные вызовы не дают констант времени компиляции (по некоторым дополнительным причинам)
person
Sebastian Mach
schedule
19.07.2011
SubDomain<i>
для всех значений<i>
, то, естественно, компилятор должен создать их все экземпляры. Это неизбежная работа. - person MSalters   schedule 19.07.2011