2010-02-28 30 views
60

Después de unas semanas de descanso, estoy tratando de expandir y extender mi conocimiento de las plantillas con el libro Plantillas – La Guía Completa por David Vandevoorde y Nicolai M. Josuttis, y lo que estoy tratando de entender en este momento es ejemplificación explícita de plantillas.Instanciación explícita: ¿cuándo se usa?

No tengo realmente un problema con el mecanismo como tal, pero no puedo imaginar una situación en la que me gustaría o quisiera utilizar esta característica. Si alguien puede explicarme eso, estaré más que agradecido.

Respuesta

38

directamente copiados de http://msdn.microsoft.com/en-us/library/by56e477%28VS.80%29.aspx:

instancias explícita permite crear una instancia de una clase o función con plantilla sin tener que usarlo en el código. Como es útil cuando está creando archivos de biblioteca (.lib) que usan plantillas para su distribución, las definiciones de plantillas no implementadas no se colocan en archivos de objetos (.obj).

(Por ejemplo, libstdC++ contiene la creación de instancias explícita de std::basic_string<char,char_traits<char>,allocator<char> > (que es std::string) por lo que cada vez que utilice funciones de std::string, el mismo código de función no tiene por qué ser copiado a los objetos. El compilador sólo necesita refiera (enlace) ésos a libstdC++.)

+6

Sí, las bibliotecas MSVC CRT tienen instanciaciones explícitas para las clases de toda la corriente, de localización y de cadena, especializada para char y wchar_t. El .lib resultante es más de 5 megabytes. –

+2

¿Cómo sabe el compilador que la plantilla se ha instanciado explícitamente en otro lugar? ¿No va a generar simplemente la definición de clase porque está disponible? –

+0

@STing: si se crea una instancia de la plantilla, habrá una entrada de esas funciones en la tabla de símbolos. – kennytm

50

Si define una clase de plantilla que solo quiere trabajar para un par de tipos explícitos.

Coloque la declaración de la plantilla en el archivo de encabezado como una clase normal.

Ponga la definición de la plantilla en un archivo fuente como una clase normal.

Luego, al final del archivo de origen, ejemplifique explícitamente solo la versión que desea que esté disponible.

ejemplo tonto:

// StringAdapter.h 
template<typename T> 
class StringAdapter 
{ 
    public: 
     StringAdapter(T* data); 
     void doAdapterStuff(); 
    private: 
     std::basic_string<T> m_data; 
}; 
typedef StringAdapter<char> StrAdapter; 
typedef StringAdapter<wchar_t> WStrAdapter; 

Fuente:

// StringAdapter.cpp 
#include "StringAdapter.h" 

template<typename T> 
StringAdapter<T>::StringAdapter(T* data) 
    :m_data(data) 
{} 

template<typename T> 
void StringAdapter<T>::doAdapterStuff() 
{ 
    /* Manipulate a string */ 
} 

// Explicitly instantiate only the classes you want to be defined. 
// In this case I only want the template to work with characters but 
// I want to support both char and wchar_t with the same code. 
template class StringAdapter<char>; 
template class StringAdapter<wchar_t>; 

principal

#include "StringAdapter.h" 

// Note: Main can not see the definition of the template from here (just the declaration) 
//  So it relies on the explicit instantiation to make sure it links. 
int main() 
{ 
    StrAdapter x("hi There"); 
    x.doAdapterStuff(); 
} 
+1

¿Es correcto decir que si el compilador tiene toda la definición de plantilla (incluidas las definiciones de funciones) en una unidad de traducción determinada, * * instanciará una especialización de la plantilla cuando sea necesario (independientemente de si esa especialización ha sido * explícitamente * instanciada en otra TU). Es decir, para obtener los beneficios de compilación/tiempo de enlace de la creación de instancias explícitas, solo se debe incluir la plantilla * declaración * para que el compilador * no pueda * crear una instancia. –

+1

@ user123456: Probablemente dependiente del compilador. Pero más que probable es cierto en la mayoría de las situaciones. –

+1

hay una manera de hacer que el compilador use esta versión explícitamente instanciada para los tipos que preespecifica, pero luego si intenta crear una instancia de la plantilla con un tipo "raro/inesperado", haga que funcione "como normal", donde simplemente ejemplifica la plantilla según sea necesario? –

Cuestiones relacionadas