c++ templates c++11 typetraits

c++ - Desambiguar el puntero de función miembro sobrecargado que se pasa como parámetro de plantilla



templates c++11 (1)

El problema está aquí:

l.call(&foo::func, "hello"); l.call(&foo::func, 0.5);

Para ambas líneas, el compilador no sabe a qué foo::func se refiere. Por lo tanto, debe desambiguarse proporcionando la información de tipo que falta (es decir, el tipo de foo:func ) mediante moldes:

l.call(static_cast<void (foo::*)(const std::string&)>(&foo::func), "hello"); l.call(static_cast<void (foo::*)(const double )>(&foo::func), 0.5);

Alternativamente, puede proporcionar los argumentos de la plantilla que el compilador no puede deducir y que definen el tipo de func :

l.call<void, const std::string&>(&foo::func, "hello"); l.call<void, double >(&foo::func, 0.5);

Tenga en cuenta que debe usar double y no const double arriba. La razón es que generalmente double y const double son dos tipos diferentes. Sin embargo, hay una situación en la que double y const double se consideran como si fueran del mismo tipo: como argumentos de función. Por ejemplo,

void bar(const double); void bar(double);

no son dos sobrecargas diferentes, pero en realidad son la misma función.

Estoy intentando recrear el patrón Observer en el que puedo reenviar parámetros perfectamente a una función miembro dada de los observadores.

Si intento pasar la dirección de una función miembro que tiene varias anulaciones , no puede deducir la función de miembro correcta en función de los argumentos.

#include <iostream> #include <vector> #include <algorithm> template<typename Class> struct observer_list { template<typename Ret, typename... Args, typename... UArgs> void call(Ret (Class::*func)(Args...), UArgs&&... args) { for (auto obj : _observers) { (obj->*func)(std::forward<UArgs>(args)...); } } std::vector<Class*> _observers; }; struct foo { void func(const std::string& s) { std::cout << this << ": " << s << std::endl; } void func(const double d) { std::cout << this << ": " << d << std::endl; } }; int main() { observer_list<foo> l; foo f1, f2; l._observers = { &f1, &f2 }; l.call(&foo::func, "hello"); l.call(&foo::func, 0.5); return 0; }

Esto no se puede compilar con template argument deduction/substitution failed .

Tenga en cuenta que tenía Args... y UArgs... porque necesito poder pasar parámetros que no son necesariamente del mismo tipo que el tipo de firma de la función, pero son convertibles a dicho tipo.

Estaba pensando que podría usar una std::enable_if<std::is_convertible<Args, UArgs>> para std::enable_if<std::is_convertible<Args, UArgs>> , pero no creo que pueda hacer esto con un paquete de parámetros de plantilla variadica.

¿Cómo puedo hacer que la deducción de argumento de la plantilla funcione aquí?