// Generic, type-safe delegates.
// (updated from blog.molecular-matters)
#include <iostream>
template<typename>
struct Delegate {};
template<typename R, typename... Args>
struct Delegate<R(Args...)>
{
Delegate()
: m_stub{nullptr, nullptr}
{}
template<R (*Function)(Args...)>
void bind(void)
{
m_stub = {nullptr, s_function_stub<Function>};
}
template<typename T, R (T::*Function)(Args...)>
void bind(T* instance)
{
m_stub = {instance, s_classmethod_stub<T, Function>};
}
R invoke(Args&&... args) const
{
if (!m_stub.second)
throw std::runtime_error("Cannot invoke unbound delegate.");
return m_stub.second(m_stub.first, std::forward<Args>(args)...);
}
private:
std::pair<void*, R (*)(void*, Args&&...)> m_stub;
template<R (*Function)(Args...)>
static R s_function_stub(void*, Args&&... args)
{
return (Function)(std::forward<Args>(args)...);
}
template<typename T, R (T::*Function)(Args...)>
static R s_classmethod_stub(void* instance, Args&&... args)
{
return (static_cast<T*>(instance)->*Function)(std::forward<Args>(args)...);
}
};
// Main.
void function()
{
std::cout << __PRETTY_FUNCTION__ << "\n";
}
struct Class
{
bool classmethod(int i, double x)
{
std::cout << __PRETTY_FUNCTION__ << " -> ";
std::cout << i << ", " << x << "\n";
return true;
}
};
int main()
{
Delegate<void()> a;
a.bind<function>();
a.invoke();
Class instance;
Delegate<bool(int, double)> b;
b.bind<Class, &Class::classmethod>(&instance);
if (b.invoke(1, 2.3))
std::cout << "true";
}
Ly8gR2VuZXJpYywgdHlwZS1zYWZlIGRlbGVnYXRlcy4KLy8gKHVwZGF0ZWQgZnJvbSBibG9nLm1vbGVjdWxhci1tYXR0ZXJzKQoKI2luY2x1ZGUgPGlvc3RyZWFtPgoKdGVtcGxhdGU8dHlwZW5hbWU+CnN0cnVjdCBEZWxlZ2F0ZSB7fTsKCnRlbXBsYXRlPHR5cGVuYW1lIFIsIHR5cGVuYW1lLi4uIEFyZ3M+CnN0cnVjdCBEZWxlZ2F0ZTxSKEFyZ3MuLi4pPgp7CiAgICBEZWxlZ2F0ZSgpCiAgICA6IG1fc3R1YntudWxscHRyLCBudWxscHRyfQogICAge30KCiAgICB0ZW1wbGF0ZTxSICgqRnVuY3Rpb24pKEFyZ3MuLi4pPgogICAgdm9pZCBiaW5kKHZvaWQpCiAgICB7CiAgICAgICAgbV9zdHViID0ge251bGxwdHIsIHNfZnVuY3Rpb25fc3R1YjxGdW5jdGlvbj59OwogICAgfQoKICAgIHRlbXBsYXRlPHR5cGVuYW1lIFQsIFIgKFQ6OipGdW5jdGlvbikoQXJncy4uLik+CiAgICB2b2lkIGJpbmQoVCogaW5zdGFuY2UpCiAgICB7CiAgICAgICAgbV9zdHViID0ge2luc3RhbmNlLCBzX2NsYXNzbWV0aG9kX3N0dWI8VCwgRnVuY3Rpb24+fTsKICAgIH0KCiAgICBSIGludm9rZShBcmdzJiYuLi4gYXJncykgY29uc3QKICAgIHsKICAgICAgICBpZiAoIW1fc3R1Yi5zZWNvbmQpCiAgICAgICAgICAgIHRocm93IHN0ZDo6cnVudGltZV9lcnJvcigiQ2Fubm90IGludm9rZSB1bmJvdW5kIGRlbGVnYXRlLiIpOwogICAgICAgIHJldHVybiBtX3N0dWIuc2Vjb25kKG1fc3R1Yi5maXJzdCwgc3RkOjpmb3J3YXJkPEFyZ3M+KGFyZ3MpLi4uKTsKICAgIH0KCnByaXZhdGU6CiAgICBzdGQ6OnBhaXI8dm9pZCosIFIgKCopKHZvaWQqLCBBcmdzJiYuLi4pPiBtX3N0dWI7CgogICAgdGVtcGxhdGU8UiAoKkZ1bmN0aW9uKShBcmdzLi4uKT4KICAgIHN0YXRpYyBSIHNfZnVuY3Rpb25fc3R1Yih2b2lkKiwgQXJncyYmLi4uIGFyZ3MpCiAgICB7CiAgICAgICAgcmV0dXJuIChGdW5jdGlvbikoc3RkOjpmb3J3YXJkPEFyZ3M+KGFyZ3MpLi4uKTsKICAgIH0KCiAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBULCBSIChUOjoqRnVuY3Rpb24pKEFyZ3MuLi4pPgogICAgc3RhdGljIFIgc19jbGFzc21ldGhvZF9zdHViKHZvaWQqIGluc3RhbmNlLCBBcmdzJiYuLi4gYXJncykKICAgIHsKICAgICAgICByZXR1cm4gKHN0YXRpY19jYXN0PFQqPihpbnN0YW5jZSktPipGdW5jdGlvbikoc3RkOjpmb3J3YXJkPEFyZ3M+KGFyZ3MpLi4uKTsKICAgIH0KfTsKCi8vIE1haW4uCgp2b2lkIGZ1bmN0aW9uKCkKewogICAgc3RkOjpjb3V0IDw8IF9fUFJFVFRZX0ZVTkNUSU9OX18gPDwgIlxuIjsKfQoKc3RydWN0IENsYXNzCnsKICAgIGJvb2wgY2xhc3NtZXRob2QoaW50IGksIGRvdWJsZSB4KQogICAgewogICAgICAgIHN0ZDo6Y291dCA8PCBfX1BSRVRUWV9GVU5DVElPTl9fIDw8ICIgLT4gIjsKICAgICAgICBzdGQ6OmNvdXQgPDwgaSA8PCAiLCAiIDw8IHggPDwgIlxuIjsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KfTsKCmludCBtYWluKCkKewogICAgRGVsZWdhdGU8dm9pZCgpPiBhOwogICAgYS5iaW5kPGZ1bmN0aW9uPigpOwogICAgYS5pbnZva2UoKTsKICAgIENsYXNzIGluc3RhbmNlOwogICAgRGVsZWdhdGU8Ym9vbChpbnQsIGRvdWJsZSk+IGI7CiAgICBiLmJpbmQ8Q2xhc3MsICZDbGFzczo6Y2xhc3NtZXRob2Q+KCZpbnN0YW5jZSk7CiAgICBpZiAoYi5pbnZva2UoMSwgMi4zKSkKICAgICAgICBzdGQ6OmNvdXQgPDwgInRydWUiOwp9