Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save sleepy-monax/58d64208c60c54a538c358deb2684bba to your computer and use it in GitHub Desktop.
Save sleepy-monax/58d64208c60c54a538c358deb2684bba to your computer and use it in GitHub Desktop.
#pragma once
#include <libutils/OwnPtr.h>
template <typename>
class Callback;
template <typename Out, typename... In>
class Callback<Out(In...)>
{
private:
class AbstractCallbackWrapper
{
public:
virtual ~AbstractCallbackWrapper() {}
virtual Out call(In...) const = 0;
};
template <typename T>
class CallbackWrapper final : public AbstractCallbackWrapper
{
private:
T _callback;
public:
CallbackWrapper(T &&callback) : _callback(move(callback)) {}
CallbackWrapper(const CallbackWrapper &) = delete;
CallbackWrapper &operator=(const CallbackWrapper &) = delete;
Out call(In... in) const { return _callback(forward<In>(in)...); }
};
OwnPtr<AbstractCallbackWrapper> _wrapper;
public:
Callback(nullptr_t) : _wrapper(nullptr) {}
template <typename CallbackType>
Callback(CallbackType &&other) : _wrapper(own<CallbackWrapper<CallbackType>>(move(other))) {}
template <typename CallbackType>
Callback(CallbackType other) : _wrapper(own<CallbackWrapper<CallbackType>>(move(other))) {}
Callback(Callback &&other) : _wrapper(other._wrapper) {}
~Callback() {}
Callback &operator=(nullptr_t)
{
_wrapper = nullptr;
return *this;
}
template <typename CallbackType>
Callback &operator=(CallbackType &&other)
{
_wrapper = own<CallbackWrapper<CallbackType>>(other);
return *this;
}
Callback &operator=(Callback &&other)
{
_wrapper = other._wrapper;
return *this;
}
Out operator()(In... in) const
{
assert(_wrapper);
return _wrapper->call(forward<In>(in)...);
}
operator bool() const { return _wrapper == nullptr; }
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment