#include <iostream>
#include <algorithm>
#include <memory>
#include <mutex>
#include <vector>
template <typename Observer>
class ObsNoti {
public:
template <
typename Ret,
typename Class,
typename... Args,
typename = std::enable_if_t<std::is_same<Observer, Class>::value>>
void notifyEveryone(Ret Class::*func, Args&&... args) {
(obs.*func)(std::forward<Args>(args)...);
}
Observer obs;
};
class ContactObserver {
public:
virtual int onContactRetrieved() {
std::cout<<"onContactRetrieved\n";
return 0;
}
virtual int onContactRetrieved(bool bSucess) {
std::cout<<"onContactRetrieved sucessfully\n";
return 0;
}
};
class MyClass : public ObsNoti<ContactObserver> {
public:
template<typename Func, bool, typename... Args>
inline void notifyObserver(Func &&func, bool b, Args&&... args) {
ObsNoti<ContactObserver>::notifyEveryone(func , b, std::forward<Args>(args)...);
}
template<typename Func, typename... Args>
inline void notifyObserver(Func &&func, Args&&... args) {
ObsNoti<ContactObserver>::notifyEveryone(func , std::forward<Args>(args)...);
}
};
int main() {
MyClass my;
my.notifyObserver(&ContactObserver::onContactRetrieved, true);
return 0;
}
I am getting the following error:
/tmp/w7Rta4F1cT.cpp:53:22: error: no matching function for call to 'MyClass::notifyObserver(<unresolved overloaded function type>, bool)'
53 | my.notifyObserver(&ContactObserver::onContactRetrieved, true);
| ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/tmp/w7Rta4F1cT.cpp:37:17: note: candidate: 'template<class Func, bool <anonymous>, class ... Args> void MyClass::notifyObserver(Func&&, bool, Args&& ...)'
37 | inline void notifyObserver(Func &&func, bool b, Args&&... args) {
| ^~~~~~~~~~~~~~
/tmp/w7Rta4F1cT.cpp:37:17: note: template argument deduction/substitution failed:
/tmp/w7Rta4F1cT.cpp:53:22: note: couldn't deduce template parameter 'Func'
53 | my.notifyObserver(&ContactObserver::onContactRetrieved, true);
| ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/tmp/w7Rta4F1cT.cpp:42:17: note: candidate: 'template<class Func, class ... Args> void MyClass::notifyObserver(Func&&, Args&& ...)'
42 | inline void notifyObserver(Func &&func, Args&&... args) {
| ^~~~~~~~~~~~~~
/tmp/w7Rta4F1cT.cpp:42:17: note: template argument deduction/substitution failed:
/tmp/w7Rta4F1cT.cpp:53:22: note: couldn't deduce template parameter 'Func'
53 | my.notifyObserver(&ContactObserver::onContactRetrieved, true);
| ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I understand the problem here is that template is unable to resolve the function at compile time because of overloading. But, I am not sure of a correct way to implement it.
Any way to resolve this?
Your code have miltiple problems:
ObsNoti::notifyEveryone
is defined to accept pointer to member variable, not pointer to member function.ContactObserver::onContactRetrieved
makes value &ContactObserver::onContactRetrieved
ambiguous and this can't be resolved during template argument deduction.To fix 1:
template <
typename Ret,
typename Class,
typename... FArgs,
typename... Args>
std::enable_if_t<std::is_same_v<Observer, Class>>
notifyEveryone(Ret (Class::*func)(FArgs...), Args&&... args)
{
(obs.*func)(std::forward<Args>(args)...);
}
To fix 2 you need use static_cast to select proper overload:
my.notifyObserver(static_cast<int (ContactObserver::*)(bool)>(&ContactObserver::onContactRetrieved), true);
https://godbolt.org/z/azYGM3cjz
or prevent deduction of first argument by explicitly providing type:
my.notifyObserver<int(ContactObserver::*)(bool)>(&ContactObserver::onContactRetrieved, true);