Skip to content

Instantly share code, notes, and snippets.

@markpapadakis
Last active August 29, 2015 14:01
Show Gist options
  • Select an option

  • Save markpapadakis/42aa05883652d524cd3f to your computer and use it in GitHub Desktop.

Select an option

Save markpapadakis/42aa05883652d524cd3f to your computer and use it in GitHub Desktop.
// A simple std::function alternative.
// You can use e.g variadic templates to support arbitrary signatures, but this here demonstrates how
// type erasure makes it possible to wrap any callable function
//
// type erasure is a nifty C++ pattern. There are alternatives to it, but this is usually a better fit.
//
// move/copy constructors and assignemnt operators not implemented, but trivial to do so anyway
// May be worth using e.g std::unique_ptr or whatever for ref-counted wrapped object for sharing, but should
// also be trivial to implement. Apparenly you need a few different alternative implementations to satisfy different
// requirements; can't practically have one impl. for everything.
struct function
{
struct interface
{
virtual ~interface(void)
{
}
virtual void invoke(void) = 0;
};
template<typename T>
struct impl
: interface
{
T value;
impl(const T &v)
: value(v)
{
}
void invoke(void) override
{
value();
}
void *operator new(size_t, void *ptr)
{
return ptr;
}
void *operator new(const size_t size)
{
return malloc(size);
}
};
interface *const binding; // just so because this can be == nullptr, otherwise we 'd use a union
uint8_t _b[128];
function(void)
: binding(nullptr)
{
}
template<typename T>
function(const T &v)
: binding(sizeof(impl<T>) <= sizeof(_b)
? new (_b)impl<T>(v)
: new impl<T>(v))
{
}
~function(void)
{
if (binding != (decltype(binding))_b)
delete binding;
else
binding->~interface();
}
void operator()(void)
{
if (binding != nullptr)
binding->invoke();
}
};
struct Callable
{
inline void operator()(void)
{
puts("Hello");
}
};
static void PrintHello(void)
{
puts("Hello");
}
int main(void)
{
//Either of those 3 will work
//function f([](void) { puts("Hello"); });
//function f((void(*)(void))PrintHello);
//Callable c; function f(c);
f();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment