I am attempting to recreate the Observer pattern where I can perfectly forward parameters to a given member function of the observers.
If I attempt to pass the address of a member function which has multiple overrides, it cannot deduce the correct member function based on the arguments.
#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;
}
This fails to compile with template argument deduction/substitution failed
.
Note that I had Args...
and UArgs...
because I need to be able to pass parameters which are not necessarily the same type asthe type of the function signature, but are convertible to said type.
I was thinking I could use a std::enable_if<std::is_convertible<Args, UArgs>>
call to disambiguate, but I don't believe I can do this with a variadic template parameter pack?
How can I get the template argument deduction to work here?
See Question&Answers more detail:os