Skip to content

Instantly share code, notes, and snippets.

@meshula
Forked from pplux/std_func_replacement.cpp
Created January 30, 2021 19:20
Show Gist options
  • Save meshula/fee1828c7fe66e4245e1db3f2831a610 to your computer and use it in GitHub Desktop.
Save meshula/fee1828c7fe66e4245e1db3f2831a610 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <assert.h>
#include <vector>
template<class T>
struct Func{};
// std::func replacement without dynamic memory allocation (captures are limited to 48 bytes)
// this could be extended to support captures >48 bytes... of course, with a bit more of logic
// and some state.
template<class R, class... Args>
struct Func<R(Args...)> {
template<class U>
Func(U &&callable) { set(std::move(callable)); }
template<class U>
Func& operator=(U &&callable) { set(std::move(callable)); return *this; }
Func(Func&& other) noexcept {
swap(std::move(other));
}
Func& operator=(Func &&other) noexcept {
swap(std::move(other));
}
~Func() {
if (_destroy) _destroy(_space);
}
R operator()(Args... args) {
return _func(_space, std::forward<Args>(args)...);
}
template<class U>
void set(U &&callable) {
assert(sizeof(U) <= sizeof(_space));
new (_space)U(std::move(callable));
_func = [](void *ptr, Args... args) -> R { return (*reinterpret_cast<U*>(ptr))(std::forward<Args>(args)...); };
_destroy = [](void *ptr) { reinterpret_cast<U*>(ptr)->~U();};
};
void swap(Func &&other) {
std::swap(_space, other._space);
std::swap(_func, other._func);
std::swap(_destroy, other._destroy);
}
R (*_func)(void *, Args...) = nullptr;
void (*_destroy)(void *) = nullptr;
uint8_t _space[64-sizeof(_func)-sizeof(_destroy)];
};
int main ()
{
int f = 5.0f;
std::vector<Func<float(int,int)>> callbacks;
callbacks.push_back([](int a, int b) -> float { return a+b;});
callbacks.push_back([f](int a, int b) -> float { return f+a+b;});
for(auto &&f: callbacks) {
printf("%f\n", f(1,2));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment