Да, это не типовой параметр. У вас может быть несколько типов параметров шаблона
- Параметры типа.
- Типы
- Шаблоны (только классы и шаблоны псевдонимов, без функций или шаблонов переменных)
- Параметры, не относящиеся к типу
- указатели
- Ссылки
- Интегральные постоянные выражения
У вас есть последнее. Это константа времени компиляции (так называемое константное выражение) целого или перечисляемого типа. После поиска в стандарте мне пришлось переместить шаблоны классов в раздел типов, хотя шаблоны не являются типами. Но они, тем не менее, называются параметрами типа для описания этих типов. У вас могут быть указатели (а также указатели членов) и ссылки на объекты / функции, которые имеют внешнюю связь (те, на которые можно ссылаться из других объектных файлов и чей адрес уникален во всей программе). Примеры:
Параметр типа шаблона:
template<typename T>
struct Container {
T t;
};
// pass type "long" as argument.
Container<long> test;
Целочисленный параметр шаблона:
template<unsigned int S>
struct Vector {
unsigned char bytes[S];
};
// pass 3 as argument.
Vector<3> test;
Параметр указателя шаблона (передача указателя на функцию)
template<void (*F)()>
struct FunctionWrapper {
static void call_it() { F(); }
};
// pass address of function do_it as argument.
void do_it() { }
FunctionWrapper<&do_it> test;
Ссылочный параметр шаблона (передача целого числа)
template<int &A>
struct SillyExample {
static void do_it() { A = 10; }
};
// pass flag as argument
int flag;
SillyExample<flag> test;
Параметр шаблона шаблона.
template<template<typename T> class AllocatePolicy>
struct Pool {
void allocate(size_t n) {
int *p = AllocatePolicy<int>::allocate(n);
}
};
// pass the template "allocator" as argument.
template<typename T>
struct allocator { static T * allocate(size_t n) { return 0; } };
Pool<allocator> test;
Шаблон без параметров невозможен. Но возможен шаблон без явных аргументов - у него есть аргументы по умолчанию:
template<unsigned int SIZE = 3>
struct Vector {
unsigned char buffer[SIZE];
};
Vector<> test;
Синтаксически template<>
зарезервировано для обозначения явной специализации шаблона вместо шаблона без параметров:
template<>
struct Vector<3> {
// alternative definition for SIZE == 3
};
static constexpr int
вместо вашегоenum
. Так что вFactorial<0>
шаблоне будетstatic constexpr int value = 1
иtemplate <int N> struct Factorial
может бытьstatic constexpr int value = N * Factorial<N - 1>::value;