c++ - sintaxis - que es pugjs
ParĂ¡metros de plantilla sin tipo (4)
Entiendo que el parámetro de la plantilla sin tipo debe ser una expresión integral constante. ¿Alguien puede arrojar luz por qué es así?
template <std::string temp>
void foo()
{
// ...
}
error C2993: ''std::string'' : illegal type for non-type template parameter ''temp''.
Entiendo lo que es una expresión integral constante. ¿Cuáles son las razones para no permitir tipos no constantes como std::string
como en el fragmento de arriba?
Debes ser capaz de modificar los argumentos de la plantilla
template <std::string temp>
void f() {
// ...
}
f<"foo">();
f<"bar">(); // different function!?
Ahora una impl necesitaría crear una secuencia única de caracteres para std::string
o, para el caso, cualquier otra clase arbitraria definida por el usuario, almacenando un valor particular, cuyo significado no se conoce para la implementación. Y, además, el valor de los objetos de clase arbitrarios no se puede calcular en tiempo de compilación.
Se planificó considerar permitir tipos de clase literales como tipos de parámetros de plantilla para post-C ++ 0x, que se inicializan mediante expresiones constantes. Esos podrían ser mutilados si los miembros de los datos se mutilan recursivamente de acuerdo con sus valores (para las clases de base, por ejemplo, podemos aplicar cruce transversal de profundidad, de izquierda a derecha). Pero definitivamente no va a funcionar para clases arbitrarias.
Eso no está permitido.
Sin embargo, esto está permitido:
template <std::string * temp> //pointer to object
void f();
template <std::string & temp> //reference to object
void g();
Ver §14.1 / 6,7,8 en C ++ Standard (2003).
Ilustración:
template <std::string * temp> //pointer to object
void f()
{
cout << *temp << endl;
}
template <std::string & temp> //reference to object
void g()
{
cout << temp << endl;
temp += "...appended some string";
}
std::string s; //must not be local as it must have external linkage!
int main() {
s = "can assign values locally";
f<&s>();
g<s>();
cout << s << endl;
return 0;
}
Salida:
can assign values locally
can assign values locally
can assign values locally...appended some string
La razón por la que no puede hacer esto es porque las expresiones no constantes no se pueden analizar y sustituir durante el tiempo de compilación. Podrían cambiar durante el tiempo de ejecución, lo que requeriría la generación de una nueva plantilla durante el tiempo de ejecución, lo que no es posible porque las plantillas son un concepto en tiempo de compilación.
Esto es lo que el estándar permite para los parámetros de plantilla sin tipo (14.1 [temp.param] p4):
Un parámetro de plantilla sin tipo debe tener uno de los siguientes tipos (opcionalmente calificado):
- tipo integral o de enumeración,
- puntero a objeto o puntero a función,
- lvalue la referencia a la referencia de objeto o lvalue a la función,
- puntero a miembro,
std::nullptr_t
.
Un argumento de plantilla no de tipo proporcionado dentro de una lista de argumentos de plantilla es una expresión cuyo valor puede determinarse en tiempo de compilación. Tales argumentos deben ser:
expresiones constantes, direcciones de funciones u objetos con enlace externo, o direcciones de miembros de clase estáticos.
Además, los literales de cadena son objetos con enlace interno, por lo que no puede usarlos como argumentos de plantilla. No puedes usar un puntero global, tampoco. Los literales de punto flotante no están permitidos, dada la posibilidad obvia de errores de redondeo.