2011-02-02 17 views
7

Escribo una clase de plantilla y quiero permitir que exista un método adicional solo para cierto tipo de plantilla. Actualmente, el método existe para todos los tipos de plantilla, pero causa un error de compilación para todos los demás tipos.¿Puedo usar boost :: enable_if en una función miembro?

Para complicar esto, se trata de un operador sobrecargado(). No estoy seguro de si lo que quiero hacer es realmente posible aquí.

Esto es lo que tengo ahora:

template<typename T, typename BASE> 
class MyClass : public BASE 
{ 
public: 

    typename T& operator() (const Utility1<BASE>& foo); 
    typename T const& operator() (const Utility2<BASE>& foo) const; 
}; 

Quiero la versión T& siempre disponible, pero la versión T const& sólo está disponible si Utility2<BASE> es válido. En este momento, ambos métodos existen, pero el intento de usar la versión const da un error de compilación extraño si Utility2<BASE> no es válido. Prefiero tener un error razonable, o incluso un error de "no función de miembro".

¿Esto es posible?

EDITAR: Después de leer a través de los documentos de impulso, esto es lo que he llegado con, y parece que funciona:

template<typename T, typename BASE> 
class MyClass : public BASE 
{ 
public: 

    typename T& operator() (const Utility1<BASE>& foo); 

    template<typename U> 
    typename boost::enable_if<boost::is_same<Utility2<BASE>, U>, T>::type const & 
    operator() (const U& foo) const; 
}; 

Por lo tanto no existe ese método a menos que alguien intenta usarlo con Utility2, y solo pueden crear una utilidad2 si es válida para ese tipo de BASE. Pero cuando no es válido para ese tipo de BASE, MyClass no perderá tiempo creando el método de acceso.

+0

¿Qué quieres decir con 'Utility2 ' es "válido"? – Nim

+0

Utility2 intenta llamar a un método en BASE. Solo un tipo de BASE en realidad tiene ese método. – Tim

+0

http://stackoverflow.com/questions/2937425/boostenable-if-class-template-method – Anycorn

Respuesta

4

Sí, esto es posible, pero no con el parámetro de plantilla de clase directamente. boost::enable_if solo se puede usar con un parámetro de plantilla en el método mismo. Así que, con un poco de uso de typedef:

template<typename T, typename BASE> 
class MyClass : public BASE 
{ 
public: 
    typedef Utility2<BASE> util; 

    typename T& operator() (const Utility1<BASE>& foo); 

    template<typename U> 
    typename boost::enable_if<boost::is_same<util, U>, T>::type const & 
    operator() (const U& foo) const; 
}; 

Esto funciona, porque Utility2 sólo puede ser creado a partir de un cierto tipo base. Entonces, si el tipo BASE es algo más, la versión const de operator() no existirá.

Por lo tanto, es una cuestión menor. No me gana mucho. Pero estuvo bien hacerlo.

Cuestiones relacionadas