Tiene que ser una expresión constante integral. Eso se explica por el documento estándar en 5.19
:
Una constante-expresión integral puede implicar sólo literales (2.13), encuestadores, variables const o miembros de datos estáticos de tipo integral o de enumeración inicializados con expresiones constantes (8,5), no tipo de parámetros de plantilla de tipo integral o de enumeración, y tamaño de expresiones. Los literales flotantes (2.13.3) solo pueden aparecer si se convierten a tipos integrales o de enumeración. Solo se pueden usar conversiones de tipos a tipos integrales o de enumeración.
Tenga en cuenta que "integral" es otro término para "entero", pero no es lo mismo que "int". "char" por ejemplo tiene un entero/tipo integral, pero no es el tipo int, obviamente. Así concretamente, se permite
10 or 10L or anything like that
enum { THIS, OR, THAT };
int const this_one = 10;
sizeof(char)
- por supuesto, cualquier otro parámetro de plantilla como se detalló anteriormente
la siguiente Cualquiera de los que pueden ser utilizado como un argumento de plantilla para un parámetro que tiene un tipo integral de th e tipo correspondiente. Algunas conversiones todavía se aplican sin embargo. Entonces, si quiere un int y pasas un char, automáticamente promueve el char al int. Lo mismo si proporciona un enumerador y quiere un int.
Así que por estas normas, si usted tiene
extern const int SomeName;
y no ver una definición por la que inicializa esa constante con una expresión constante integral, no puede ser utilizado como un argumento de plantilla. Pero puede usarse como un argumento de función, por supuesto. No es necesario conocerlos en tiempo de compilación porque no son parte de un tipo. En el momento de nombrar a una especialización de plantilla, los argumentos que ha utilizado se convierten en parte del tipo:
MyGreatStack<int, 4> // 4 is now part of the type MyGreatStack<int, 4>!
Tenga en cuenta que no son otros formas de pasar SomeName
como argumento. Sin embargo, todos los cuales pueden no ser aceptados por un parámetro de plantilla entero. Puede aceptar lo anterior mediante un parámetro de referencia, por ejemplo
template<const int& V> struct NowItWorks { };
y sería aceptar la SomeName
de arriba. Ahora, en lugar de un valor, se ha elegido una ubicación particular que es única en todo el programa (ya que la variable tiene el enlace extern
).