Ando haciendo pruebas últimamente con C++ y hay algo que ahora no soy capaz de hacer, que es que elija entre un método u otro dependiendo de si lo que se le pasa por parámetro es una función o un functor.
Concretamente tengo algo como esto:
template<typename T, typename Proxy = queue_proxy<T> > class channel { public: template<typename Result> channel<Result, typename Proxy::template bind<Result>::type> operator>>(Result (&receiver)(T)) { channel<Result, typename Proxy::template bind<Result>::type> out_channel; threads.push_back(new boost::thread(create_stream_channel_thread(*this, out_channel, receiver))); return channel<Result, typename Proxy::template bind<Result>::type>(out_channel); } }; |
La idea es que este código permite hacer algo como lo siguiente:
int fac(int x) { if(x < 1) return 1; return x * fac(x-1); } void show(int x) { std::cout << x << std::endl; } /* some code here */ channel<int> ch; /* Se redirige el canal a fac y la salida del factorial a show */ ch >> fac >> show; /* more code here */ |
Sí, el código se parece mucho a Axum de Microsoft, que la idea es crear algo parecido para C++.
El caso es que el operador funciona bien cuando se pasan funciones, pero no funciona si le paso un functor, como podría ser el caso siguiente:
class functor { public: functor() {} int operator()(int a) { /* do something interesting */ } }; /* some code here */ channel<int> ch; ch >> functor() >> show; |
La cosa es que no sé como hacer para detectar que se me pasa un functor y qué parametros son los que tiene, aunque aún tengo que hacer alguna prueba más antes de dar por imposible la tarea.
operator()(int) debe ser ‘const’ en el functor. ¿O qué problema estás teniendo?
El problema, concretamente, es que no puedo identificar si es o no un functor y en el caso de que sea un functor cual es el tipo de retorno del mismo.
La gracia de los templates es que no tengas que identificar si es un functor o no. Es decir, si en un objeto se puede aplicar el operador () pues se aplica, independientemente de si es una función o un functor. Ahora bien, el asunto del tipo de retorno no es tan simple… para eso creo que instanciar los templates lo cual es feo para el operador << y mucho menos elegante.
En general, bibliotecas como boost lo que hacen es considerar que se le pasan functores y si no es un functor entonces tienes que hacer un bind de la función. Lo que yo estaba tratando de hacer es bucar un mecanismo que lo haga de forma transparente al programador.