Sí, es un parámetro que no es de tipo. Puede tener varios tipos de parámetros de plantilla
- Tipo de parámetros.
- Tipos
- Plantillas (solo clases y plantillas de alias, sin funciones ni plantillas de variables)
- Parámetros que no son de tipo
- Punteros
- Referencias
- Expresiones constantes integrales
Lo que tienes ahí es del último tipo. Es una constante de tiempo de compilación (la denominada expresión constante) y es de tipo entero o enumeración. Después de buscarlo en el estándar, tuve que mover las plantillas de clase a la sección de tipos, aunque las plantillas no son tipos. Pero se les llama parámetros de tipo con el propósito de describir esos tipos de todos modos. Puede tener punteros (y también punteros a miembros) y referencias a objetos / funciones que tienen vínculos externos (aquellos a los que se pueden vincular desde otros archivos de objeto y cuya dirección es única en todo el programa). Ejemplos:
Parámetro de tipo de plantilla:
template<typename T>
struct Container {
T t;
};
// pass type "long" as argument.
Container<long> test;
Parámetro de número entero de plantilla:
template<unsigned int S>
struct Vector {
unsigned char bytes[S];
};
// pass 3 as argument.
Vector<3> test;
Parámetro de puntero de plantilla (pasar un puntero a una función)
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;
Parámetro de referencia de plantilla (pasando un número entero)
template<int &A>
struct SillyExample {
static void do_it() { A = 10; }
};
// pass flag as argument
int flag;
SillyExample<flag> test;
Parámetro de plantilla de plantilla.
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;
No es posible una plantilla sin parámetros. Pero una plantilla sin ningún argumento explícito es posible, tiene argumentos predeterminados:
template<unsigned int SIZE = 3>
struct Vector {
unsigned char buffer[SIZE];
};
Vector<> test;
Sintácticamente, template<>
está reservado para marcar una especialización de plantilla explícita, en lugar de una plantilla sin parámetros:
template<>
struct Vector<3> {
// alternative definition for SIZE == 3
};
static constexpr int
lugar de suenum
. Entonces laFactorial<0>
plantilla tendríastatic constexpr int value = 1
, ytemplate <int N> struct Factorial
puede tenerstatic constexpr int value = N * Factorial<N - 1>::value;