Skip to content

Instantly share code, notes, and snippets.

@mmitou
Created February 24, 2012 17:18
Show Gist options
  • Select an option

  • Save mmitou/1902148 to your computer and use it in GitHub Desktop.

Select an option

Save mmitou/1902148 to your computer and use it in GitHub Desktop.
オブジェクトとメソッドを一纏めにして呼び出せるようにしたもの。
#ifndef __MY_FUNCTION_HPP__
#define __MY_FUNCTION_HPP__
#include <boost/shared_ptr.hpp>
struct Holder
{
virtual ~Holder(){};
};
template <class Method>
struct DerivedHolder
:public Holder
{
DerivedHolder(Method m):method(m){};
Method method;
};
template <class Signature> class Function;
template <>
class Function<void ()>
{
public:
template <class Obj, class Method>
Function(Obj *obj, Method method)
:pHolder(new DerivedHolder<Method> (method))
{
pObj = reinterpret_cast<void*>(obj);
invoke = &Invoker<Obj, Method>::invoke;
}
void operator()()
{
invoke(pObj, pHolder);
}
private:
void *pObj;
boost::shared_ptr<Holder> pHolder;
void (*invoke)(void *, boost::shared_ptr<Holder>);
template <class Obj, class Method>
struct Invoker
{
static void invoke(void *o, boost::shared_ptr<Holder> h)
{
Obj *obj = reinterpret_cast<Obj*>(o);
Holder *pHolder = h.get();
DerivedHolder<Method> *pDerivedHolder =
dynamic_cast<DerivedHolder<Method>*>(pHolder);
Method method = pDerivedHolder->method;
(obj->*method)();
}
};
};
template <class R>
class Function<R ()>
{
public:
template <class Obj, class Method>
Function(Obj *obj, Method method)
:pHolder(new DerivedHolder<Method> (method))
{
pObj = reinterpret_cast<void*>(obj);
invoke = &Invoker<Obj, Method>::invoke;
}
R operator()()
{
return invoke(pObj, pHolder);
}
private:
void *pObj;
boost::shared_ptr<Holder> pHolder;
R (*invoke)(void *, boost::shared_ptr<Holder>);
template <class Obj, class Method>
struct Invoker
{
static R invoke(void *o, boost::shared_ptr<Holder> h)
{
Obj *obj = reinterpret_cast<Obj*>(o);
Holder *pHolder = h.get();
DerivedHolder<Method> *pDerivedHolder =
dynamic_cast<DerivedHolder<Method>*>(pHolder);
Method method = pDerivedHolder->method;
return (obj->*method)();
}
};
};
template <class Arg0>
class Function<void (Arg0)>
{
public:
template <class Obj, class Method>
Function(Obj *obj, Method method)
:pHolder(new DerivedHolder<Method> (method))
{
pObj = reinterpret_cast<void*>(obj);
invoke = &Invoker<Obj, Method>::invoke;
}
void operator()(Arg0 arg0)
{
invoke(pObj, pHolder, arg0);
}
private:
void *pObj;
boost::shared_ptr<Holder> pHolder;
void (*invoke)(void *, boost::shared_ptr<Holder>, Arg0);
template <class Obj, class Method>
struct Invoker
{
static void invoke(void *o,
boost::shared_ptr<Holder> h,
Arg0 arg0
)
{
Obj *obj = reinterpret_cast<Obj*>(o);
Holder *pHolder = h.get();
DerivedHolder<Method> *pDerivedHolder =
dynamic_cast<DerivedHolder<Method>*>(pHolder);
Method method = pDerivedHolder->method;
(obj->*method)(arg0);
}
};
};
#endif// __MY_FUNCTION_HPP__
#include "Function.hpp"
#include <iostream>
class Foo
{
public:
void method()
{
std::cout << "Foo::method()" << std::endl;
}
int method0()
{
std::cout << "int Foo::method0()" << std::endl;
return 0;
}
int method1(double x)
{
std::cout << "int Foo::method0(double) " << x << std::endl;
return 1;
}
};
class Bar
{
public:
void method()
{
std::cout << "Bar::method()" << std::endl;
}
int method0()
{
std::cout << "int Bar::method0()" << std::endl;
return 0;
}
};
int main()
{
Foo *foo = new Foo;
Bar *bar = new Bar;
Function<void ()> f(foo, &Foo::method);
Function<void ()> b(bar, &Bar::method);
Function<int ()> f0(foo, &Foo::method0);
Function<int ()> b0(bar, &Bar::method0);
Function<void (double)> f1(foo, &Foo::method1);
f();
b();
std::cout << f0() <<std::endl;
b0();
f1(11.22);
delete foo;
delete bar;
return 0;
}
@mmitou

mmitou commented Feb 24, 2012

Copy link
Copy Markdown
Author

Foo::method()
Bar::method()
int Foo::method0()
0
int Bar::method0()
int Foo::method0(double) 11.22

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment