2012-01-30 12 views
23

Este es un seguimiento de este problema: Generic functor for functions with any argument list¿Cómo obtengo los tipos de argumento de un puntero de función en una clase de plantilla variadica?

tengo esta clase funtor (código completo ver enlace anterior):

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...); } 
}; 

en el operador() que pueda acceder a los argumentos ... con facilidad una función recursiva "peeling" como se describe aquí http://www2.research.att.com/~bs/C++0xFAQ.html#variadic-templates

Mi problema es: Quiero acceder a los tipos de los argumentos de f, es decir, ARGS ..., en el constructor. Obviamente no puedo acceder a los valores porque no hay ninguno hasta el momento, pero la lista de tipo de argumento está de alguna manera oculta en f, ¿no es así?

Respuesta

48

Puede escribir function_traits clase como se muestra a continuación, para descubrir los tipos de argumentos, tipo de retorno, y el número de argumentos:

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; 
    }; 
}; 

Código de ensayo:

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; 
} 

Demostración: http://ideone.com/YeN29

+0

Gracias @Nawaz, funciona hasta ahora. Sin embargo, me gustaría extraer la "magia" de esta solución y ponerla en mi código. Supongo que typename std :: tuple_element > :: type es donde ocurre ... ¿Cómo hago eso sin tener que declarar otra estructura? – steffen

+0

@steffen: ¿Tiene algún problema para definir otra estructura? que también se puede usar en otras situaciones? Además, poner todo el código en una sola clase no es una buena idea. Intenta dividir el código en pequeñas unidades de trabajo. – Nawaz

+0

Entiendo tu punto. Una última pregunta es esta pieza de código de la biblioteca de impulso? function_traits suena familiar;) – steffen

Cuestiones relacionadas