2012-01-30 5 views
23

Si tratta di un follow-up di questo problema: Generic functor for functions with any argument listCome si ottengono i tipi di argomento di un puntatore a funzione in una classe modello variadic?

ho questa classe funtore (codice completo vedi link qui sotto):

template<typename... ARGS> 
class Foo 
{ 
    std::function<void(ARGS...)> m_f; 
    public: 
    Foo(std::function<void(ARGS...)> f) : m_f(f) {} 
    void operator()(ARGS... args) const { m_f(args...); } 
}; 

Operatore() posso accedere ai args ... facilmente con una funzione ricorsiva "peeling" come descritto qui http://www2.research.att.com/~bs/C++0xFAQ.html#variadic-templates

Il mio problema è: voglio accedere ai tipi di argomenti di f, cioè ARGS ..., nel costruttore. Ovviamente non posso accedere ai valori perché non ce ne sono finora, ma l'elenco dei tipi di argomenti è in qualche modo nascosto in f, non è vero?

risposta

48

È possibile scrivere function_traits classe come mostrato di seguito, per scoprire i tipi di argomento, tipo di ritorno, e il numero di argomenti:

template<typename T> 
struct function_traits; 

template<typename R, typename ...Args> 
struct function_traits<std::function<R(Args...)>> 
{ 
    static const size_t nargs = sizeof...(Args); 

    typedef R result_type; 

    template <size_t i> 
    struct arg 
    { 
     typedef typename std::tuple_element<i, std::tuple<Args...>>::type type; 
    }; 
}; 

Codice di prova:

struct R{}; 
struct A{}; 
struct B{}; 

int main() 
{ 
    typedef std::function<R(A,B)> fun; 

    std::cout << std::is_same<R, function_traits<fun>::result_type>::value << std::endl; 
    std::cout << std::is_same<A, function_traits<fun>::arg<0>::type>::value << std::endl; 
    std::cout << std::is_same<B, function_traits<fun>::arg<1>::type>::value << std::endl; 
} 

Demo: http://ideone.com/YeN29

+0

Grazie @Nawaz, lavora fino ad ora. Tuttavia, vorrebbe estrarre la "magia" da questa soluzione e inserirla nel mio codice. Suppongo che std :: tuple_element > :: type sia dove accade ... Come faccio a farlo senza dover dichiarare un'altra struttura – steffen

+0

@steffen: Hai qualche problema nel definire un'altra struttura che può essere utilizzato anche in altre situazioni? Inoltre, inserire tutto il codice in una sola classe non è una buona idea. Prova a dividere il codice in piccole unità di lavoro. – Nawaz

+0

Ho capito il tuo punto. Un'ultima domanda è questa parte di codice dalla libreria boost? function_traits suona familiare;) – steffen

Problemi correlati