2011-10-04 21 views
5

Decir que tengo esto:plantilla con la plantilla de múltiples parámetros

template<typename T, int X> 
class foo 
{ 
public: 
    void set(const T &t); 
}; 

template<typename T, int X> 
void foo::set<T, X>(const T &t) 
{ 
    int s = X; 
    // ...etc 
} 

¿Podría especializar el tipo de función 'T', pero dejan 'X' como un parámetro de plantilla?

class bar; 

template<int X> 
void foo::set<bar, X>(const bar &t) 
{ 
    int s = X; 
    // ...etc 
} 

Es esto posible?

+1

'void foo :: set (const T & t)' -> 'void foo :: conjunto (const T & t)' –

Respuesta

6

Esto es sorprendentemente fácil una vez que el cuelgue de ella

template<typename T, int X> 
class foo 
{ 
private: 
    template<typename, int> class params { }; 

public: 
    void set(const T &t) { 
    set(t, params<T, X>()); 
    } 

private: 
    template<typename T1, int X1> 
    void set(const T1 &t, params<T1, X1>) { 
    // ... 
    } 

    template<int X1> 
    void set(const bar &t, params<bar, X1>) { 
    // ... 
    } 
}; 

Esto es necesario porque si se especializan explícitamente un solo miembro, debe proporcionar todos los argumentos de plantilla . No puedes dejar un poco.

+0

Eso es correcto, pero yo personalmente evitaría tales trucos. Hace que el código sea ilegible. La especialización parcial de IMO de la clase o algo similar según la situación (por ejemplo, crear una plantilla de clase base y especializarla parcialmente e implementar (¿muchas?) Funciones no especializadas en clases derivadas no especializadas) es una decisión mucho mejor. –

+0

@Serge specialization parcial se especializa toda la clase. Por lo tanto, no es adecuado si solo desea un comportamiento especial para una sola función. crear una plantilla base es mucho más ruidoso e inconveniente (no tendrás acceso a los miembros de "foo", ...). Si tiene una solución más limpia a la anterior, le invito a que la publique. –

+0

"especialización parcial se especializa toda la clase" - Verdadero. "Crear una plantilla base es mucho más ruidoso e inconveniente". Por lo general, no es un inconveniente, es un trabajo adicional de menor importancia hacer que la arquitectura sea consistente. Si existe una necesidad de especialización, normalmente existe una lógica especial sobre este caso que podría merecer una especialización de clase (base) por separado. Si hay muchos objetos miembros comunes, entonces no hay problema en ponerlos (protegidos) en otra clase para que sean la base para ambas especializaciones principales (y generalmente hay una lógica detrás de esto). –

2

No. Eso no está permitido. Una función miembro classdebe estar completamente especializada. Por ejemplo, debería ser,

template<> 
void foo<bar, 5>::set(const bar &t) 
{   //^^^^ 
    int s = 5; 
    // ...etc 
} 
1

Puede parcialmente especializar toda la clase. En este caso, puede dar diferentes implementaciones a la función set para cada especialización de la clase.

+0

¿Puedes dar un ejemplo? – MarkP

+0

@MarkP, compruebe [this] (http://stackoverflow.com/questions/1535816/c-partial-method-specialization/1535845#1535845) answer. –

3

usted podría considerar volver a escribir el código para hacer la función de miembro de una plantilla separada:

template <int X> class foo 
{ 
    template <typename T> void set(const T &); 
    // ... 
}; 

A continuación, le puede proporcionar especializaciones explícitas para la plantilla foo<X>::set.

Cuestiones relacionadas