【问题标题】:std::fuction calling conventionstd::function 调用约定
【发布时间】:2022-01-22 00:07:04
【问题描述】:

我的代码中有观察者实现。它看起来像这样:

template <typename... Args>
class Event {
    std::map<size_t, std::function<void(Args...)>> m_observers;
    mutable std::mutex m_mutex;
public:
    virtual ~Event() = default;

    [[nodiscard]] size_t Register(const size_t& object_id, std::function<void(Args...)> observer) {

        std::lock_guard<std::mutex> lk(m_mutex);
        m_observers[object_id] = observer;
        return object_id;
    }

为简洁起见,我没有在此处添加完整的课程代码。 以及连接对象的代码:

class Object {
    std::wstring m_name;
    size_t m_id=0;
public:
    Object() { GenerateID(); }
    Object(std::wstring name) : m_name(name) { GenerateID(); }
    virtual ~Object() = default;

    size_t GetID() const { return m_id; }

    template <class T, typename... Args>
    size_t ObjectConnect(void(T::* callback_fn)(Args...args), Event<Args...>* obj_event);

    template <typename... Args>
    size_t ObjectConnect(std::function<void> fn(Args...args), Event<Args...>* obj_event);
private:
    void GenerateID();
};

template<class T, typename... Args>
size_t Object::ObjectConnect(void(T::* callback_fn)(Args... args), Event<Args...>* obj_event) {
    auto fn = [this, callback_fn](Args... args)->void {((static_cast<T*>(this))->*callback_fn)(args...); };
    return obj_event->Register(m_id, fn);
}

template<typename ...Args>
inline size_t Object::ObjectConnect(std::function<void> fn(Args...args), Event<Args...>* obj_event)
{
    return obj_event->Register(m_id, fn);
}

第一种ObjectConnect 函数与子类的成员函数完美配合。我添加了第二个重载,以便能够传递带有附加参数的成员函数:

std::function<void(bool)> fn1 = [this, serverName](bool param) {this->OnServerConnection(serverName.toStdWString(), param); };
    ObjectConnect(fn1, Refactoring::Backend::GetManagerByName(serverName.toStdWString())->GetConnectionEvent());

不幸的是,它给了我下一个错误:

Error   C2784   'size_t Design::Object::ObjectConnect(std::function<void> (__cdecl *)(Args...),Design::Event<Args...> *)': could not deduce template argument for 'std::function<void> (__cdecl *)(Args...)' from 'std::function<void (bool)>'

从错误消息看来,它似乎与调用约定有关,但我不知道该怎么做,谷歌搜索也没有给我任何线索。

【问题讨论】:

    标签: c++ observer-pattern


    【解决方案1】:

    这与调用约定无关:所有成员函数在 C++ 中都有相同的调用约定(有时称为“thiscall”),而std::function&lt;T&gt;::operator() 是一个成员函数。

    相反,问题在于您的函数原型采用std::function&lt;T&gt; 是不正确的。签名在模板参数列表中,如下所示:

    template <typename... Args>
    size_t ObjectConnect(std::function<void(Args...)> fn, Event<Args...>* obj_event);
    

    【讨论】:

    • 我不明白为什么 OPs 代码仍然编译没有错误 (godbolt.org/z/qrcnvfzo5)。 fn(Args...) 被解释为默认参数?
    • @463035818_is_not_a_number 正如所写,OP 的 fn 参数类型是一个函数,采用 Args... 并返回 std::function&lt;void&gt;(这是一个不完整的类型;您实际上不能实例化它,但它在声明中使用是有效的)。
    • 它不像你建议的那样编译。编译器错误:错误 C3646 'fn':未知的覆盖说明符
    • @goodle06 它为我编译。
    • @KonradRudolph 哇,我的错。真的错过了,谢谢。现在它工作正常。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-27
    • 2014-01-08
    • 2012-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多