Skip to content

Instantly share code, notes, and snippets.

@lsem
Last active July 30, 2022 16:03
Show Gist options
  • Save lsem/a05653b1facc20461fdc3d433594eec3 to your computer and use it in GitHub Desktop.
Save lsem/a05653b1facc20461fdc3d433594eec3 to your computer and use it in GitHub Desktop.
f2ptr
#include <cassert>
#include <cstdio>
#include <string>
using namespace std;
namespace f2ptr {
namespace details {
template <class...> struct type_list {};
// Helper meta-function needed to derive correct signature of our C-style
// function.
template <class F>
struct func_traits : public func_traits<decltype(&F::operator())> {};
template <class ClassType, class R, class... Args>
struct func_traits<R (ClassType::*)(Args...) const> {
using return_type = R;
using args_type = type_list<Args...>;
};
class f2ptr_impl {
public:
template <class F> static auto get(F f) {
return get_impl(typename func_traits<F>::args_type{}, std::move(f));
}
private:
template <class F, class... Args>
static auto get_impl(type_list<Args...>, F f) {
static F std_func = std::move(f);
return +[](Args... args) ->
typename func_traits<F>::return_type { return std_func(args...); };
}
};
} // namespace details
template <class F> auto f2ptr(F f) {
return details::f2ptr_impl::get(std::move(f));
}
} // namespace f2ptr
void take_callbacks(void (*cb1)(int, char), void (*cb2)(int));
int main() {
int local_i = 0;
take_callbacks(f2ptr::f2ptr([&](int i, char) { puts("f1"); }),
f2ptr::f2ptr([&](int i) { puts("f2"); }));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment