2012-01-03 34 views
7

el siguiente código:C++: la especialización parcial de clases de plantilla plantilla

using namespace std; 

template <typename X> 
class Goo {}; 


template <typename X> 
class Hoo {}; 


template <class A, template <typename> class B = Goo > 
struct Foo { 
    B<A> data; 
    void foo1(); 
    void foo2(); 

}; 


template <typename A> 
void Foo<A>::foo1() { cout << "foo1 for Goo" << endl;} 


int main() { 
    Foo<int> a; 
    a.foo1(); 

} 

me da un error del compilador:

test.cc:18: error: invalid use of incomplete type 'struct Foo<A, Goo>' 
test.cc:11: error: declaration of 'struct Foo<A, Goo>' 

Por qué no puedo parcialmente especializarse foo1()? Si este no es el camino, ¿cómo hago esto?

Tengo otra pregunta: ¿qué pasa si quiero que foo2() se defina solo para A = int, B = Hoo y no para ninguna otra combinación, ¿cómo hago eso?

+1

Esto no es una especialización parcial, Foo toma dos parámetros y aquí sólo se especifica una en 'Foo :: foo1'. –

+0

Y qué es X en Goo . Goo es una plantilla que toma un parámetro X. ¿Dónde está especificado? – jmucchiello

Respuesta

4

Las plantillas de función solo pueden ser totalmente especializadas, no parcialmente.

Las funciones miembro de plantillas de clase son automáticamente funcionan las plantillas, y pueden de hecho ser especializados, pero sólo plenamente:

template <> 
void Foo<int, Goo>::foo1() { } // OK 

puede especializarse parte de toda la clase y luego definirlo de nuevo:

template <typename A> 
struct Foo<A, Goo> 
{ 
    // ... 
}; 

(Ver 14.7.3 para más detalles.)

+0

No creo que esté tratando de especializarse. Editar: Ah, sí, por "especialización parcial" quiere omitir uno de los parámetros. – someguy

+0

Entonces, ¿no hay forma de especializar parcialmente un método miembro de una clase de plantilla, sin especializar toda la clase? – user231536

+0

@ user231536: No, de hecho. Aquí hay una [respuesta anterior similar] (http://stackoverflow.com/a/7517290/596781). –

1

La plantilla todavía tiene dos parámetros, y estoy UST escribir algo como esto:

template <typename A, template <typename> class B> 
void Foo<A,B>::foo1() { cout << "foo1" << endl;} 

El valor por defecto se ha especificado, y sólo necesita ser especificado una vez. A partir de ese momento, es como cualquier otra plantilla de dos parámetros. Este código se aplicará independientemente de qué B sea (predeterminado o no). Si luego desea especificar un comportamiento diferente para un B en particular, y luego, usted se especializa en la clase, no solo en un método.

(pesadamente corregida)

+0

Creo que una combinación de la respuesta de @ KerreckSB, y quizás la mía, podría ser correcta. No estoy seguro de cuál es el objetivo final. En última instancia, creo que un 'foo1()' totalmente no especializado tendrá que implementarse tarde o temprano, como el que he escrito. –

Cuestiones relacionadas