2011-10-07 10 views
5

Tengo una clase A que tiene un parámetro de plantilla T. Hay casos de uso donde la clase T ofrece una función func1() y hay casos de uso donde T doesn no lo ofrezco Una función f() en A debería llamar a func1(), si existe. Creo que esto debería ser posible con boost mpl, pero no sé cómo. Aquí algunos pseudo-código:Boost MPL: Llame a una función (miembro) solo si existe

template<class T> 
class A 
{ 
    void f(T param) 
    { 
     if(T::func1 is an existing function) 
      param.func1(); 
    } 
}; 

Aún mejor sería una cosa de los casos:

template<class T> 
class A 
{ 
    void f(T param) 
    { 
     if(T::func1 is an existing function) 
      param.func1(); 
     else 
      cout << "func1 doesn't exist" << endl; 
    } 
}; 
+2

Incluso si logra encontrar una condición adecuada, ese código no se compilará. Ambas ramas de if deben compilarse, y si la función no existe, la rama verdadera no compilará. –

+0

Con la especialización de plantillas, no es necesario compilar ambas partes. De alguna manera tendría que llamar a una función de plantilla con el parámetro T y esta función tiene un comportamiento diferente cuando T ofrece o no ofrece func1(). Estoy seguro de que boost mpl ofrece algo para este caso de uso. Simplemente no sé cómo usarlo. – Heinzi

+0

¿Es C++ 11 una opción? –

Respuesta

7

Boost.MPL no se ocupa de que a medida que es estrictamente para TMP y no se puede llamar a los miembros en TMP. Boost.Fusion y Boost.TypeTraits tampoco tienen nada; Pensé que uno de ellos lo haría, pero aparentemente estoy recordando mal.

Here y here son algunas soluciones sobre cómo escribir un rasgo para detectar un miembro en C++ 03. Una vez que tenga un rasgo (voy a llamarlo has_func1_member), que se puede utilizar para SFINAE:

template<typename T> 
typename boost::enable_if<has_func1_member<T> >::type 
maybe_call(T& t) 
{ t.func1(); } 

template<typename T> 
typename boost::disable_if<has_func1_member<T> >::type 
maybe_call(T&) 
{ 
    // handle missing member case 
} 

// your example code would then do: 
maybe_call(param); 

Tenga en cuenta que con C++ 11 es más fácil de escribir el rasgo en el primer lugar, aunque todavía algo arcano

+0

¿Realmente tendría que escribirlo usted mismo? ¿No es is_member_function_pointer el truco? http://en.cppreference.com/w/cpp/types/is_member_function_pointer o en Boost: http://www.boost.org/doc/libs/1_51_0/libs/type_traits/doc/html/boost_typetraits/reference/is_member_function_pointer .html – Gurgeh

+0

@Gurgeh En C++ 03 no ayuda. En C++ 11 es posible que pueda escribir algo que funcione, pero es probable que falle con funciones de miembro sobrecargadas (informará un falso negativo) y hay formas más sencillas de hacerlo sin ese inconveniente. –

Cuestiones relacionadas