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();
}
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. –
¿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? –
@STing: si se crea una instancia de la plantilla, habrá una entrada de esas funciones en la tabla de símbolos. – kennytm