2010-10-16 9 views
6

Decir que tengo la clase siguiente:¿Cómo especializo un miembro estático de una clase de plantilla en un tipo de plantilla?

template<class T> 
struct A 
{ 
    static int value; 
}; 

template<class T> 
int A<T>::value = 0; 

puedo especializar A::value en un tipo concreto sin problemas:

struct B 
{ 
}; 

template<> 
int A<B>::value = 1; 

me gustaría especializarse A :: valor a un tipo de plantilla, lo intentado el siguiente:

template<class T> 
struct C 
{ 
}; 

// error: template definition of non-template 'int A<C<T> >::value' 
template<> 
template<class T> 
int A<C<T> >::value = 2; 

¿hay alguna manera de hacer esto o es sólo posible especializarse a :: valor de los tipos no de plantilla?

Respuesta

7

En lugar de introducir una especialización explícita entera, sólo podría especializar la inicialización

template<class T> 
struct Value { 
    static int const value = 0; 
}; 

template<class T> 
struct Value< C<T> > { 
    static int const value = 2; 
}; 

template<class T> 
int A<T>::value = Value<T>::value; 
+0

+1: puede que quiera decir Valor :: valor. – Chubsdad

+0

@Chubsdad es una definición de OP's A :: value. Vaue :: value no necesita una definición. –

2

Puede utilizar la especialización parcial de A a través de C:

#include <iostream> 

using namespace std; 

template<class T> 
struct A 
{ 
    static int value; 
}; 

template<class T> 
int A<T>::value = 0; 

//(1) define the C template class first: 
template<class T> 
struct C 
{ 
}; 

//(2) then define the partial specialization of A, in terms of C: 
template<typename T> 
struct A<C<T> > 
{ 
    static int value; 
}; 

template<typename T> 
int A<C<T> >::value = 2; 

int main(void) 
{ 
    cout<<A<C<int> >::value<<endl; 

    cout<<"ok!"<<endl; 
    return 0; 
} 
+0

Esto funciona, pero no es tan flexible como la respuesta que acepté. Tengo la intención de extender la clase A para otros tipos definidos por el usuario, y con esto necesitaría tener todas las especializaciones de A definidas antes de usar A, en lugar de poder definir especializaciones de valor en cualquier lugar, y dejar que el vinculador haga el trabajo. –

+0

Ok, si entendí bien tu punto, (comprensiblemente) te gustaría no vincular las especializaciones de A a las definiciones de plantillas preexistentes, y proporcionar una nueva especialización cada vez que defines un nuevo nombre de tipo, como C, parametrizado por un argumento de plantilla. Una solución para eso es usar especialización parcial a través de un argumento plantilla-plantilla (ver abajo mi segunda respuesta). Espero que ayude. –

0

especialización parcial a través de un parámetro de plantilla en la plantilla (vea mi comentario arriba):

#include <iostream> 

using namespace std; 

template<class T> 
struct A 
{ 
    static int value; 
}; 

template<class T> 
int A<T>::value = 0; 



//solution 2: 
//define a template-template argument partial specialization 
//for any generic class U depending on a template argument, 
//(which is a typename, in this case, but there's no reason why 
//you wouldn't define specializations for non-types, etc.) 
//this specialization has the advantage of not depending on 
//the template definition of U (or C, etc.); in this case 
//both T and U are free to vary, with the only constraint 
//that U is parameterized by T: 
template<typename T, template<typename> class U> 
struct A<U<T> > 
{ 
    static int value; 
}; 

template<typename T, template<typename> class U> 
int A<U<T> >::value = 3; 

//define the C template class, somewhere, where/when/if needed 
//possibly in a different namespace, "module" (etc.) 
template<class T> 
struct C 
{ 
}; 

int main(void) 
{ 
    cout<<A<C<int> >::value<<endl;//this now should print out: 3 

    cout<<"ok!"<<endl; 
    return 0; 
} 
Cuestiones relacionadas