2009-08-23 28 views
7

que quieran especializarse siguiente función miembro:plantilla de especialización de clase de plantilla

class foo { 
    template<typename T> 
    T get() const; 
}; 

Para otra clase bar que depende de las plantillas también.

Por ejemplo, me gustaría ser barstd::pair con algunos parámetros de plantilla, algo así:

template<> 
std::pair<T1,T2> foo::get() const 
{ 
    T1 x=...; 
    T2 y=...; 
    return std::pair<T1,T2>(x,y); 
} 

Donde T1 y T2 son las plantillas también. ¿Cómo puede hacerse esto? Por lo que sé, debería ser posible.

Así que ahora puedo llamar:

some_foo.get<std::pair<int,double> >(); 

La respuesta final completo /:

template<typename T> struct traits; 
class foo { 
    template<typename T> 
    T get() const 
    { 
     return traits<T>::get(*this); 
    } 
}; 

template<typename T> 
struct traits { 
    static T get(foo &f) 
    { 
     return f.get<T>(); 
    } 
}; 

template<typename T1,typename T2> 
struct traits<std::pair<T1,T2> > { 
     static std::pair<T1,T2> get(foo &f) 
     { 
       T1 x=...; 
       T2 y=...; 
       return std::make_pair(x,y); 
     } 
}; 
+0

No está claro lo que quieres decir. ¿Desea una especialización que se aplique siempre que T1 y T2 sean plantillas? ¿O cuando son una plantilla específica? ¿O cuando son plantillas y su parámetro es de algún tipo específico? – jalf

+0

Quiero decir, que quiero especializar mi función para otro tipo específico (como std :: pair) que también necesita algunos parámetros de plantilla. – Artyom

+0

Compruebe esto: http://stackoverflow.com/questions/947943/template-specialisation-where-templated-type-is-also-a-template –

Respuesta

8

No puede especializarse parcialmente plantillas de función, lo siento, pero esas son las reglas. Usted puede hacer algo como:

class foo { 
    ... 
}; 


template<typename T> 
struct getter { 
    static T get(const foo& some_foo); 
}; 

template<typename T1, typename T2> 
struct getter< std::pair<T1, T2> > { 
static std::pair<T1, T2> get(const foo& some_foo) { 
    T1 t1 = ...; 
    T2 t2 = ...; 
    return std::make_pair(t1, t2); 
}; 

y luego llamar así

getter<std::pair<int, double> >::get(some_foo); 

sin embargo. Es posible que tenga que jugar un poco con friend enviar o visibilidad si get realmente necesita ser una función miembro.

Para más detalles sobre la sugerencia de OSE:

class foo { 
    ... 
    template<typename T> 
    T get() const; 
}; 

template<typename T> 
T foo::get() const 
{ 
    return getter<T>::get(*this); 
    /*   ^-- specialization happens here */ 
} 

Y ahora que has vuelto a ser capaz de decir

std::pair<int,double> p = some_foo.get<std::pair<int, double> >(); 
+1

Podría. sin embargo, haz que 'getter' sea un miembro (prossibly' private') de la clase y haz que se llame a través de una plantilla de función de miembro normal. De esta forma, los usuarios de su clase no tienen que preocuparse por este mecanismo. – sbi

+0

@sbi, ese es un gran punto. –

1

Es necesario sobrecargar su función de miembro de par, como en

template <T, V> std::pair<T, V> foo::get() 

En el caso general, tendrá que ser capaz de desambiguar entre las diversas sobrecargas. En el caso, la desambiguación es fácil porque el par se modela en 2 tipos, mientras que el miembro original se modeló solo en T.

Si por el contrario necesitas una especialización para, por ejemplo, std :: vector, que es para un contenedor con una plantilla de parámetro único, debes tener cuidado ya que puede ser confuso para el compilador saber si deseas una instancia de la especialización de plantilla en la plantilla T es std :: vector o la especialización para la sobrecarga,

template <T> std::<vector <T> foo::get() const 

Su sintaxis propuesta no puede trabajar ya que se especializan por completo la función miembro,

template <>,

pero está omitiendo dos tipos no especificados, T1 y T2.

+0

Esto no funciona: "prototype for' std :: pair <_T1, _T2> foo :: get() 'no coincide con ninguno en la clase' foo'; candidate is: template T foo :: get() " – Artyom

+0

tendrías que declarar por la clase foo 'plantilla std :: par get() const;' y luego llamarlo algo así como: 'std :: par p_int = f.get (); ' – Francesco

Cuestiones relacionadas