I have the following class for building callback functions to any subset of function type, be it static function, lambda, lambda w/ capture list, static class functions or member class functions. Problem is that it doesn't take overloads because there's no parameter resolution when passing functions to the templated constructor(s):
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); }
};
Usage: (fails on overloads, remove overloads and it compiles)
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);
}