2010-04-29 21 views
9

Uno de mis experimentos personales para comprender algunas de las características de C++ 0x: estoy tratando de pasar un puntero a una función de plantilla para ejecutar. Eventualmente, se supone que la ejecución sucederá en un hilo diferente. Pero con todos los diferentes tipos de funciones, no puedo hacer que las plantillas funcionen.Plantillas, punteros de función y C++ 0x

#include <functional> 

int foo(void) {return 2;} 

class bar { 
public: 
    int operator() (void) {return 4;}; 
    int something(int a) {return a;}; 
}; 

template <class C> 
int func(C&& c) 
{ 
    //typedef typename std::result_of< C() >::type result_type; 
    typedef typename std::conditional< 
     std::is_pointer<C>::value, 
     std::result_of< C() >::type, 
     std::conditional< 
      std::is_object<C>::value, 
      std::result_of< typename C::operator() >::type, 
      void> 
     >::type result_type; 
    result_type result = c(); 
    return result; 
} 

int main(int argc, char* argv[]) 
{ 
    // call with a function pointer 
    func(foo); 

    // call with a member function 
    bar b; 
    func(b); 

    // call with a bind expression 
    func(std::bind(&bar::something, b, 42)); 

    // call with a lambda expression 
    func([](void)->int {return 12;}); 

    return 0; 
} 

La plantilla result_of por sí solo no parece ser capaz de encontrar el operador() en la barra de clase y la torpe condicional creé no se compila. ¿Algunas ideas? ¿Tendré problemas adicionales con las funciones de const?

+0

Quizás la razón por la que no compila es porque 'func' devuelve' int' en lugar de 'result_type' (que en este ejemplo es' int' en todos los casos, pero aún puede causar un problema)? –

+0

@Chris: No, esa no es la razón. – kennytm

+0

@KennyTM - Pensé que no, pero aún creo que es un problema. –

Respuesta

6

¿Qué le parece usar decltype?

template <class C> 
auto func(C&& c) -> decltype(c()) { 
    auto result = c(); 
    return result; 
} 
+0

que parece mucho más limpio. ¡Gracias! – user328543

4

si entiendo el proyecto de C++ 0x derecha la siguiente realidad debería ser suficiente:

typedef typename std::result_of<C()>::type result_type; 

El uso que en lugar de su expresión condicional, se compila bien en gcc4.5 - tal vez usted tiene encontrado un error en el compilador que está utilizando?

+0

eso es lo que yo también pensé, pero no compiló. Todo el complejo condicional fue creado para solucionarlo. – user328543

+1

@ user328543: Si hago un comentario sobre su condicional y uso la línea previamente comentada compila absolutamente bien en gcc4.5. –

2

Tengo su plantilla para crear instancias, pero GCC se queja de posiblemente cada uso de result_of.

template <class C> 
int func(C&& c) 
{ 
    //typedef typename std::result_of< C() >::type result_type; 
    typedef typename std::conditional< 
     std::is_pointer<C>::value, 
     // C++0x still requires "typename" sprinkles: 
     typename std::result_of< C() >::type, 
     typename std::conditional< 
      std::is_object<C>::value, 
      // result_of takes a *type* as an argument, not an object: 
      //typename std::result_of< decltype(&C::operator()) >::type, 
      // Or better: 
      typename std::result_of<C>::type, 
      void> 
     >::type result_type; 
    result_type result = c(); 
    return result; 
} 

int main(int argc, char* argv[]) 
{ 
    // according to GCC, func(foo) passes a function reference. 
    func(foo); 

primer mensaje de error:

rof.cpp:23:17: error: invalid use of incomplete type 'struct std::result_of<int (&)()>' 

result_of se implementa como se especifica en la norma, por lo que se deduce que las CGC no puede coincidir con la sintaxis de pseudo-prototipo en la declaración de la especialización parcial.

+0

Las referencias a las funciones deberían funcionar: * "Fn debe ser un tipo de objeto de función (20.8), referencia a función o referencia al tipo de objeto de función." * –

+1

@gf: genial, bueno, voy a mantener el comentario como útilmente pedante. De cualquier manera, el mensaje de error de GCC muestra claramente que está rechazando el código bueno. – Potatoswatter

+0

@gf: ¿hilo equivocado? – Potatoswatter