Skip to content

Instantly share code, notes, and snippets.

@petebarber
Created December 7, 2015 14:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save petebarber/6ea915a7e61e0902fffa to your computer and use it in GitHub Desktop.
Save petebarber/6ea915a7e61e0902fffa to your computer and use it in GitHub Desktop.
#include <iostream>
#include <vector>
#include <string>
class ISimpleBoundFunctorBase
{
public:
ISimpleBoundFunctorBase(const std::string& id)
: _id(id)
{
// For debugging
}
virtual ~ISimpleBoundFunctorBase() =default;
const std::string& id() const
{
return _id;
}
bool compare(const ISimpleBoundFunctorBase& rhs) const
{
return safeCompare(rhs);
}
virtual void invoke() =0;
private:
virtual bool safeCompare(const ISimpleBoundFunctorBase&) const = 0;
const std::string _id;
};
template<typename T, typename MEM_FN_RET>
class SimpleBoundTypedFunctor : public ISimpleBoundFunctorBase
{
private:
MEM_FN_RET (T::*_memFun)();
T& _t;
public:
SimpleBoundTypedFunctor(MEM_FN_RET (T::*memFun)(), T& t, const std::string& id)
: ISimpleBoundFunctorBase(id)
, _memFun(memFun)
, _t(t)
{
}
void invoke() override
{
if (_memFun)
(_t.*_memFun)();
}
bool operator==(const SimpleBoundTypedFunctor& rhs) const
{
return (&_t == &rhs._t) && (_memFun == rhs._memFun);
}
private:
bool safeCompare(const ISimpleBoundFunctorBase& rhs) const override
{
const SimpleBoundTypedFunctor& rhsOfTheCorrectType = static_cast<const SimpleBoundTypedFunctor&>(rhs);
return operator==(rhsOfTheCorrectType);
}
};
class SimpleBoundErasedFunctor
{
private:
struct Dummy;
unsigned char memory[sizeof(SimpleBoundTypedFunctor<Dummy, void>)];
ISimpleBoundFunctorBase* _typedFunctor;
public:
template<typename T, typename MEM_FN_RET>
SimpleBoundErasedFunctor(MEM_FN_RET (T::*memFun)(), T& t, const std::string id)
{
// NOTE: If the function was larger than memory could be allocated
static_assert(sizeof(SimpleBoundTypedFunctor<T, MEM_FN_RET>) <= sizeof(memory), "Whoops!");
_typedFunctor = new (&memory) SimpleBoundTypedFunctor<T, MEM_FN_RET>(memFun, t, id);
}
void invoke()
{
_typedFunctor->invoke();
}
bool operator==(const SimpleBoundErasedFunctor& rhs) const
{
return _typedFunctor->compare(*rhs._typedFunctor);
}
// For debugging
const std::string& Id() const { return _typedFunctor->id(); }
};
template<typename T>
SimpleBoundErasedFunctor MakeSimpleBoundErasedFunctor(void (T::*memFun)(), T& t)
{
return SimpleBoundErasedFunctor(memFun, t);
}
class Foo
{
public:
void f() { std::cout << "Foo::f()\n"; }
void g() { std::cout << "Foo::g()\n"; }
};
class Bar
{
public:
void f() { std::cout << "Bar::f()\n"; }
};
int main()
{
void (Foo::*f)() = &Foo::f;
void (Foo::*f1)() = &Foo::f;
void (Foo::*g)() = &Foo::g;
std::cout << "f==f1:" << std::boolalpha << (f == f1) << '\n';
std::cout << "f==g:" << (f == g) << '\n';
Foo foo, foo1;
SimpleBoundTypedFunctor<Foo, void> a(&Foo::f, foo, "a::f");
SimpleBoundTypedFunctor<Foo, void> a1(&Foo::f, foo1, "a1::f");
a.invoke();
Foo foo2;
SimpleBoundTypedFunctor<Foo, void> b(&Foo::f, foo2, "b::f");
std::cout << "a == a:" << (a == a) << '\n';
std::cout << "a == a1:" << (a == a1) << '\n';
std::cout << "a == b:" << (a == b) << '\n';
std::vector<ISimpleBoundFunctorBase*> handles;
handles.push_back(&a);
handles.push_back(&a1);
handles.push_back(&b);
for (const ISimpleBoundFunctorBase* me : handles)
for (const ISimpleBoundFunctorBase* other : handles)
std::cout << "me(" << me->id() << ") == other(" << other->id() << "):" << (me->compare(*other)) << '\n';
std::vector<SimpleBoundErasedFunctor> handles1;
Bar bar;
handles1.push_back(SimpleBoundErasedFunctor(&Foo::f, foo, "Foo::f"));
handles1.push_back(SimpleBoundErasedFunctor(&Bar::f, bar, "Bar::f"));
handles1.push_back(SimpleBoundErasedFunctor(&Foo::g, foo, "Foo::g"));
for (auto& obj : handles1)
obj.invoke();
for (SimpleBoundErasedFunctor& me : handles1)
for (SimpleBoundErasedFunctor& other : handles1)
std::cout << "me(" << me.Id() << ") == other(" << other.Id() << "):" << (me == other) << '\n';
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment