Skip to content

Instantly share code, notes, and snippets.

@vittorioromeo
Created July 12, 2017 20:34
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 vittorioromeo/a41eb1c825bfbb43f595b13bd4ea99c3 to your computer and use it in GitHub Desktop.
Save vittorioromeo/a41eb1c825bfbb43f595b13bd4ea99c3 to your computer and use it in GitHub Desktop.
#include <functional>
#include <utility>
#include <type_traits>
#include <iostream>
template <typename TSignature>
class function_ref;
template <typename TReturn, typename... TArgs>
class function_ref<TReturn(TArgs...)> final
{
private:
using signature_type = TReturn(void*, TArgs...);
void* _ptr;
TReturn (*_erased_fn)(void*, TArgs...);
public:
template <typename T, typename = std::enable_if_t<
std::is_invocable<T&, TArgs...>{} &&
!std::is_same<std::decay_t<T>, function_ref>{}>>
function_ref(T&& x) noexcept : _ptr{(void*)std::addressof(x)}
{
_erased_fn = [](void* ptr, TArgs... xs) -> TReturn {
return (*reinterpret_cast<std::add_pointer_t<T>>(ptr))(
std::forward<TArgs>(xs)...);
};
}
decltype(auto) operator()(TArgs... xs) const
noexcept(noexcept(_erased_fn(_ptr, std::forward<TArgs>(xs)...)))
{
return _erased_fn(_ptr, std::forward<TArgs>(xs)...);
}
};
int main()
{
function_ref<void()> f{[i = 0]() mutable { std::cout << i++; }};
f();
f();
f();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment