自定义回调函数不能重载

问题描述 投票:0回答:1

我有以下类,用于为函数类型的任何子集构建回调函数,无论是静态函数、lambda、带捕获列表的 lambda、静态类函数还是成员类函数。问题是它不需要重载,因为在将函数传递给模板化构造函数时没有参数解析:

template<typename... A>
class callback {
protected:
    /// Unique identifying hash code.
    size_t hash;
    /// The function bound to this callback.
    std::function<void(A...)> bound;

public:
    /// Binds a static or lambda function.
    template<class Fx>
    void bind_callback(Fx func) {
        bound = [func = std::move(func)](A... args) { std::invoke(func, args...); };
        hash = bound.target_type().hash_code();
    }

    /// Binds the a class function attached to an instance of that class.
    template<typename T, class Fx>
    void bind_callback(T* obj, Fx func) {
        bound = [obj, func = std::move(func)](A... args) { std::invoke(func, obj, args...); };
        hash = std::hash<T*>{}(obj) ^ bound.target_type().hash_code();
    }

    /// Create a callback to a static or lambda function.
    template<typename T, class Fx> callback(T* obj, Fx func) { bind_callback(obj, func); }

    /// Create a callback to a class function attached to an instance of that class.
    template<class Fx> callback(Fx func) { bind_callback(func); }

    /// Compares the underlying hash_code of the callback function(s).
    bool operator == (const callback<A...>& cb) { return hash == cb.hash; }

    /// Inequality Compares the underlying hash_code of the callback function(s).
    bool operator != (const callback<A...>& cb) { return hash != cb.hash; }

    /// Returns the unique hash code for this callback function.
    constexpr size_t hash_code() const throw() { return hash; }

    /// Invoke this callback with required arguments.
    callback<A...>& invoke(A... args) { bound(args...); return (*this); }
};

用法:(重载失败,删除重载并编译)

myclass {
public:
    void function(float x) {}
    void function(int x) {}
    static inline void static_function(float x) {}
    static inline void static_function(int x) {}
}

static inline void function(float x) {}
static inline void function(int x) {}

int main() {
    myclass inst;
    callback<int> mycallback(&inst, &myclass::function);
    callback<int> mycallback(&function);
    callback<int> mycallback(&myclass::static_function);
}
c++ function overloading std-invoke
1个回答
0
投票

在 Together C & C++ discord 上的某人的帮助下,在

std::type_identity_t
中使用
C++20
的建议解决了问题(以及对使用 lambda 的捕获列表的轻微修改)。您可以使用
std::type_identity_t<...>
来解决重载函数的歧义类型。这用以下内容替换了原始构造函数——
bind_callback
函数不需要此参数解析,因为它已经使用构造函数完成了,但是我们必须将它们移动到私有以避免手动重新绑定,我不这样做无论如何都不允许。

然而,使用

std::type_identity_t
对类型定义更加明确,强制重新定义构造函数以涵盖所有情况(静态、lambda、捕获列表 lambda、静态类和成员函数)。

private:
/// Binds a static or lambda function.
template<class Fx>
void bind_callback(Fx func) {
    bound = [func = std::move(func)](A... args) { std::invoke(func, args...); };
    hash = bound.target_type().hash_code();
}

/// Binds the a class function attached to an instance of that class.
template<typename T, class Fx>
void bind_callback(T* obj, Fx func) {
    bound = [obj, func = std::move(func)](A... args) { std::invoke(func, obj, args...); };
    hash = std::hash<T*>{}(obj) ^ bound.target_type().hash_code();
}

public:
/// Create a callback to a static or lambda function.
template<typename T>
callback(T* obj, std::type_identity_t<void (T::*)(A...)> func) { bind_callback(obj, func); }

/// Create a callback to a static or lambda function.
template<typename T>
callback(std::type_identity_t<void (T::*)(A...)> func) { bind_callback(func); }

/// Create a callback to a class function attached to an instance of that class.
template<typename Lx>
callback(Lx func) { bind_callback(func); }

/// Create a callback to a class function attached to an instance of that class.
callback(std::type_identity_t<void(A...)> func) { bind_callback(func); }
© www.soinside.com 2019 - 2024. All rights reserved.