Skip to content

Instantly share code, notes, and snippets.

@xueliu
Last active April 29, 2019 13:31
Show Gist options
  • Save xueliu/3a00ea64633a11b8dd3354eb658b32fd to your computer and use it in GitHub Desktop.
Save xueliu/3a00ea64633a11b8dd3354eb658b32fd to your computer and use it in GitHub Desktop.
#ifndef _DELEGATE_H_
#define _DELEGATE_H_
/**
* non specialized template declaration for delegate
*/
template <typename T>
class delegate;
/**
* specialization for member functions
*
* \tparam T class-type of the object who's member function to call
* \tparam R return type of the function that gets captured
* \tparam params variadic template list for possible arguments
* of the captured function
*/
template <typename T, typename R, typename... Params>
class delegate<R (T::*)(Params...)>
{
public:
typedef R (T::*func_type)(Params...);
delegate(func_type func, T& callee)
: callee_(callee)
, func_(func)
{}
R operator()(Params... args) const
{
return (callee_.*func_)(args...);
}
bool operator==(const delegate& other) const
{
return (&callee_ == &other.callee_) && (func_ == other.func_);
}
bool operator!= (const delegate& other) const
{
return !((*this) == other);
}
private:
T& callee_;
func_type func_;
};
/**
* specialization for const member functions
*/
template <typename T, typename R, typename... Params>
class delegate<R (T::*)(Params...) const>
{
public:
typedef R (T::*func_type)(Params...) const;
delegate(func_type func, const T& callee)
: callee_(callee)
, func_(func)
{}
R operator()(Params... args) const
{
return (callee_.*func_)(args...);
}
bool operator==(const delegate& other) const
{
return (&callee_ == &other.callee_) && (func_ == other.func_);
}
bool operator!= (const delegate& other) const
{
return !(*this == other);
}
private:
const T& callee_;
func_type func_;
};
/**
* specialization for free functions
*
* \tparam R return type of the function that gets captured
* \tparam params variadic template list for possible arguments
* of the captured function
*/
template <typename R, typename... Params>
class delegate<R (*)(Params...)>
{
public:
typedef R (*func_type)(Params...);
delegate(func_type func)
: func_(func)
{}
R operator()(Params... args) const
{
return (*func_)(args...);
}
bool operator==(const delegate& other) const
{
return func_ == other.func_;
}
bool operator!= (const delegate& other) const
{
return !((*this) == other);
}
private:
func_type func_;
};
/**
* function to deduce template parameters from call-context
*/
template <typename F, typename T>
delegate<F> make_delegate(F func, T& obj)
{
return delegate<F>(func, obj);
}
template <typename T>
delegate<T> make_delegate(T func)
{
return delegate<T>(func);
}
// a little backward compatilbility layer
#define DELEGATE make_delegate
#define DELEGATE_CONST make_delegate
#define DELEGATE_FREE make_delegate
#endif /* end of include guard */
#include <iostream>
#include "delegate.hpp"
class A
{
public:
void deadSimple()
{
printf("no params whatsoever\n");
}
int foo(int x)
{
return x*x;
}
int bar(int x, int y, char a)
{
return a == 'a' ? x+y : x*y;
}
void crazy(int I, char wanna, float go, const char* crazy)
{
printf("I=%d, wanna=%c, go=%f, crazy=%s\n",
I, wanna, go, crazy);
}
};
int main()
{
A a;
auto d = DELEGATE(&A::foo, a);
auto d2 = DELEGATE(&A::bar, a);
auto d3 = DELEGATE(&A::crazy, a);
auto d4 = DELEGATE(&A::deadSimple, a);
printf("d(42)=%d\n", d(42));
printf("d2(42, 2, 'a')=%d\n", d2(42, 2, 'a'));
const char* s = "sheeeet!";
d3(5, 'a', 4.5, s);
d4();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment