2011-10-07 12 views
5

Ho una classe A che ha un parametro template T. Ci sono casi d'uso in cui la classe T offre una funzione func1() e ci sono casi d'uso in cui T doesn lo offro. Una funzione f() in A dovrebbe chiamare func1(), se esiste. Penso che questo dovrebbe essere possibile con boost mpl, ma non so come. Ecco alcuni pseudo codice:Boost MPL: chiama una funzione (membro) solo se esiste

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

Ancora meglio sarebbe un altro caso:

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

Anche se si riesce a trovare una condizione corretta, il codice non verrà compilato. Entrambi i rami di if devono essere compilati e se la funzione non esiste, il ramo vero non verrà compilato. –

+0

Con la specializzazione del modello non è necessario che entrambe le parti vengano compilate. In qualche modo dovrei chiamare una funzione template con il parametro T e questa funzione ha un comportamento diverso quando T offre o non offre func1(). Sono sicuro che boost mpl offre qualcosa per questo caso d'uso. Non so come usarlo. – Heinzi

+0

C++ 11 è un'opzione? –

risposta

7

Boost.MPL non si occupa che come è rigorosamente per TMP e non si può chiamare i membri in TMP. Anche Boost.Fusion e Boost.TypeTraits non hanno nulla; Pensavo che uno di loro sarebbe stato, ma a quanto pare stavo rimuginando.

Here e here sono alcune soluzioni su come scrivere un tratto per rilevare un membro in C++ 03. Una volta che hai una tale caratteristica (lo chiamerò has_func1_member), è possibile utilizzarlo per 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); 

Si noti che con il C++ 11 è più facile scrivere il tratto, in primo luogo, anche se è ancora un po 'arcano.

+0

Dovresti davvero scrivere da solo? Non è_member_function_pointer fare il trucco? http://en.cppreference.com/w/cpp/types/is_member_function_pointer o in 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 In C++ 03 non aiuta. In C++ 11 potresti essere in grado di scrivere qualcosa che funziona, ma probabilmente fallirà con funzioni membro sovraccariche (segnalerà un falso negativo) e ci sono modi più semplici per farlo senza tale inconveniente. –

Problemi correlati