2011-05-13 22 views
13

Hoy estoy al día. Aquí va n00b pregunta número 7:Diferencia entre la especialización explícita y las funciones normales al sobrecargar una función de plantilla

¿Cuál es la diferencia entre la especialización explícita y las funciones normales cuando intenta sobrecargar una función de plantilla?

¿Cuál es la situación adecuada para utilizar la especialización explícita? Yo no lo entiendo del todo:

#include <iostream> 

template <typename s> void test(s var1); 
template <> void test<int>(int var1); 

int main(){ 
    test(1); 
    test(1.1); 
    test("hello!!"); 
    return 0; 
} 

template <typename s> void test(s var1){ 
    std::cout << var1 << std::endl; 
} 

template <> void test<int>(int var1){ 
    std::cout << "int " << var1 << std::endl; 
} 

como se oponen a:

#include <iostream> 

template <typename s> void test(s var1); 
void test(int var1); 

int main(){ 
    test(1); 
    test(1.1); 
    test("hello!!"); 
    return 0; 
} 

template <typename s> void test(s var1){ 
    std::cout << var1 << std::endl; 
} 

void test(int var1){ 
    std::cout << "int " << var1 << std::endl; 
} 
+0

+1, buena pregunta. A menudo uso para pensar sobre esto hace algún tiempo. :) – iammilind

Respuesta

6

Realmente no hay una diferencia entre una función de plantilla especializada y de forma explícita una función regular no molde aparte del hecho que cuando el compilador busque un tipo de firma coincidente para la llamada a la función, primero seleccionará una función que no sea de plantilla que coincida con la firma requerida antes de tratar de instanciar cualquier función de plantilla disponible que pueda cumplir con la coincidencia de firma requerida.

Si van a declarar y definir una función dentro de un archivo de cabecera que es no una función de plantilla, sin embargo, tendrá que declarar la función como inline. Esto se debe a que una función de plantilla no es una función real que está vinculada con un módulo de código hasta que realmente se crea una instancia. El enlazador tira esa instanciación luego de compilar el módulo de código. Si el enlazador no hizo esto, cada vez que un archivo .cpp incluye el archivo de encabezado, el enlazador se quejaría acerca de las definiciones duplicadas para una función. El uso de la palabra clave inline en una función no plantilla tiene un efecto similar en el nivel de compilación, ya que cada vez que la función se utiliza en un archivo .cpp, el compilador reemplaza esa llamada de función con el cuerpo del código de función de la función inline en el archivo de encabezado, y evita la sobrecarga de una llamada a función con una configuración y limpieza de registro de pila activa asociada. Por lo tanto, el vinculador no se quejará de definiciones duplicadas para una función.

+0

reemplazando el código? Entonces, ¿eso significa que la función en línea también tendrá acceso a las variables de la función que lo llamó? – Pwnna

+0

@ultimatebuster: No, la función en línea no tiene acceso a las variables de la función de llamada. Consulte http://www.parashift.com/c++-faq-lite/inline-functions.html para obtener todos los detalles, pero la clave es que 'inline' es simplemente una sugerencia/solicitud al compilador de que el compilador es gratuito. ignorar. –

+0

@ultimatebuster No, no es así. Esa es una de las diferencias importantes y la razón para preferir las funciones en línea a las macros. El compilador aún respeta y aplica el alcance. – greatwolf

0

En mi humilde opinión, especialización explícita para function template se debe utilizar cuando, va a llamar a esa función utilizando el argumento de plantilla explícita. p.ej.

test<int>(myClass); // no argument for 'int' -> declare test() as template specialization 

En otros casos, siempre debe utilizar la especialización normal. p.ej.

test(10, myClass); // argument 10 is 'int' -> test() should be normal specialized 

Técnicamente no hay diferencia entre la especialización de plantilla normal y explícita de una función. Las versiones especializadas normales son completamente independientes de las funciones template.

+0

No veo cómo responde esto a la pregunta. –

+0

He respondido, '¿Cuál es la situación apropiada para usar la especialización explícita?' – iammilind

3

La principal diferencia es que las especializaciones explícitas no participan en la sobrecarga.

template<typename T> void f(T const&); 
template<> void f<char const*>(char const * const&); 

Llamar con f("hello") no tendrá en cuenta ningún especializaciones explícitos. Solo tomará todas las plantillas y deducirá sus argumentos de plantilla. El T anterior se deducirá a char[6], por lo que no se seleccionará la especialización.

Si sobrecarga la plantilla de función en su lugar, tiene características completamente diferentes.

template<typename T> void f(T const&); 
void f(char const * const&); 

Llamar a este, se selecciona la segunda función, debido a que tanto el parámetro (char const(&)[6]) de la especialización generado y el parámetro (char const * const&) coinciden con el argumento igualmente bien, pero la segunda función es una función no plantilla, por lo tanto es preferido eventualmente.

3

No soy un experto, pero mi experiencia es usar plantillas (y especialización) cuando quiero definir diferentes tipos de devolución. No puede sobrecargar el tipo de devolución de una función.

1

Cuando el compilador encuentra una llamada de función, primero busca una definición de función no de plantilla, luego una plantilla explícitamente especializada y, finalmente, una definición de plantilla cuya firma coincide con la llamada de función. Entonces, por ejemplo, si tiene una plantilla y una plantilla explícitamente definidas, entonces el compilador se aplica a la plantilla explícitamente definida. Por lo tanto, debe usar una plantilla explicity specialzed cuando desee manejar un tipo de datos particular de una manera diferente a la forma en que la plantilla lo habría manejado.

Otro uso para la especialización explícita es cuando se quiere "sobrecargar" una función que no toma ningún argumento. Puede usar especialización explícita para dar diferentes definiciones a la función para manejar diferentes tipos de datos.

Cuestiones relacionadas