2009-10-08 19 views
10

¿Hay una especialización parcial para el método de clase de plantilla?C++ especialización de método parcial

template <class A, class B> 
class C 
{ 
    void foo(); 
} 

no funciona especializarse así:

template <class A> void C<A, CObject>::foo() {}; 

Cualquier ayuda?

+0

Hay un par de formas mostradas en otras respuestas: http://stackoverflow.com/questions/1501357/template-specialization-of-particular-members/1501455#1501455 –

Respuesta

11

Si ya está ha especializado clase que pueden dar otros implementación de foo en clase especializada:

template<typename A, typename B> 
class C 
{ 
public: 
    void foo() { cout << "default" << endl; }; 
}; 

template<typename A> 
class C<A, CObject> 
{ 
public: 
    void foo() { cout << "CObject" << endl; }; 
}; 

especializarse función miembro en Visual C++ 2008 que podría hacer template también:

template<typename A, typename B> 
class C 
{ 
    template<typename T> 
    void foo(); 

    template<> 
    void foo<CObject>(); 
}; 

La solución anterior parece estar disponible solo en futuros estándares de C++ (según el borrador n2914 14.6.5.3/2)

+0

Mientras que el segundo es correcto, el primero es incorrecto; no se pueden poner especializaciones explícitas en el alcance de clase; incluso si se especifica la especialización de la plantilla en el ámbito del espacio de nombres, si se especializa una plantilla, todas las plantillas adjuntas deben estar especializadas también :(Entonces tiene que seguir con la segunda forma. –

+0

Así que esto no funcionará, por ejemplo: 'template template <> void C :: foo () {}', porque mientras la plantilla de función de miembro es especializada, la externa aún no. Se puede hacer al revés a través de 'plantilla <> plantilla void C :: foo() {}' pero sospecho que esto no es lo que él quiere hacer -.- –

+0

Primero parece que no cumple con C++ 03, pero funciona en Visual C++ 2008. Parece una extensión de C++ 0x (14.6.5.3 Miembros de la plantilla de clase specia lizaciones). –

1

Puesto que la clase es la plantilla, es necesario que especializarse:

template <class A> 
class C<A, CObject> 
{ 
    void foo() { ... } 
} 
+0

Ya tengo una clase especializada, pero necesito exactamente especializar el método :) – faya

0

Si no recuerdo mal, no se puede hacer especialización de plantilla parcial para funciones. No está seguro de si está incluida en C++ 0X

Actualización: (pendiente de confirmación) Como se señaló en los comentarios, especialización de plantilla parcial de las funciones es posible en C++ 0X.

+0

Esta restricción se levanta en C++ 0x –

+0

@yngvedh, ¿tiene una referencia para esa nota de "Actualización"? No he oído hablar de esto todavía. Afaik, solo levantan los argumentos predeterminados, es decir, puedes tener argumentos predeterminados en las plantillas de funciones. –

+0

@libt, sin referencia. Supuse que the_drow sabía de lo que estaba hablando, ya que no soy un experto en C++ 0X. ¿Alguien en el saber puede confirmar esto? Actualizaré apropiadamente. –

8

Creo que hay un malentendido allí.

Hay dos tipos de plantillas:

  • las clases de plantilla
  • los métodos plantilla

en su ejemplo, usted tiene una clase de plantilla, que por supuesto contiene algunos métodos. En este caso, tendrás que especializar la clase.

template <class A> 
class C<A,CObject> 
{ 
    void foo() { ... } // specialized code 
}; 

El problema en su ejemplo es relativamente simple: se define el foo método para la especialización C, pero esta especialización nunca ha sido declarado de antemano.

El problema aquí es que tienes que especializar completamente tu clase C (y copiar así muchos datos). Hay una serie de soluciones.

  • Herencia (Composición?): haga todo el trabajo común en una clase base, luego haga que la clase C herede y se especialice según corresponda
  • Amigo: en lugar de tener el método 'foo' como miembro de C, defínalo como un amigo libre de funciones y especialícese Sólo este método
  • Delegación: tiene su método de 'foo' llamar a otro método de 'bar', que es una función gratuita, y se especializan 'bar' apropiadamente

que en código da:

// 1- Inheritance 
template <class A, class B> 
class CBase 
{ 
    // Everything that does not require specialization 
}; 

template <class A, class B> 
class C: public CBase<A,B> 
     // depending on your need, consider using another inheritance 
     // or even better, composition 
{ 
    void foo(); // generic 
}; 

template <class A> 
class C<A,CObject> : public CBase<A,CObject> 
{ 
    void foo(); // specialized 
}; 

// 2- Friend 
// note the change in signature: 
// - now you need to pass the attributes to be changed 
// - the last parameter helps differentiating the overload 
// as there is no specialization for functions 
template <class A, class B> void foo(Arg1&, Arg2&, const B&); 
template <class A> void foo(Arg1&, Arg2&, const CObject&); 

template <class A, class B> 
class C 
{ 
    friend template <class, class> foo; 
}; 

// 3- Delegation 
// same signature as foo in (2) 
template <class A, class B> void bar(Arg1&, Arg2&, const B&); 
template <class A> void bar(Arg1&, Arg2&, const CObject&); 

template <class A, class B> 
class C 
{ 
    void foo() { bar(member1, member2, B()); } 
}; 

¡Espero que aclare y ayude!

2

No, no se debe agregar ninguna especialización de plantilla de función parcial en C++ 0x.

Como se ha mencionado anteriormente correctamente, con respecto a las plantillas de función básicamente 2 cosas se hicieron: se pusieron a disposición

  • argumentos de plantilla por defecto;
  • se introdujeron plantillas variadic.

Así como antes, se deben utilizar soluciones para "emular" la especialización de plantillas de funciones parciales.

Cuestiones relacionadas