c++ 参数包无法解析重载函数

blpfk2vs  于 2023-04-13  发布在  其他
关注(0)|答案(1)|浏览(154)
#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;
}

我收到以下错误:

/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);
      |     ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

我知道这里的问题是因为重载,模板在编译时无法解析函数。但是,我不确定正确的实现方法。
有办法解决吗?

68bkxrlz

68bkxrlz1#

你的代码有很多问题:

  1. ObsNoti::notifyEveryone被定义为接受指向成员变量的指针,而不是指向成员函数的指针。
  2. ContactObserver::onContactRetrieved的重载使值&ContactObserver::onContactRetrieved不明确,在模板参数推导期间无法解决此问题。
    要修复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)...);
    }

要修复2,您需要使用static_cast来选择适当的重载:

my.notifyObserver(static_cast<int (ContactObserver::*)(bool)>(&ContactObserver::onContactRetrieved), true);

https://godbolt.org/z/azYGM3cjz
或通过显式提供类型来防止第一个参数的推导:

my.notifyObserver<int(ContactObserver::*)(bool)>(&ContactObserver::onContactRetrieved, true);

https://godbolt.org/z/E3avEbhr5

相关问题