code copied from clang/lib/Parse/ParseDecl.cpp#L4426
#include <type_traits>
#include <utility>
#include <cstdint>
#include <iostream>
#include <functional>
template <typename T>
struct remove_cvref // NOLINT(readability-identifier-naming)
{
using type = std::remove_cv_t<std::remove_reference_t<T>>;
};
template <typename T>
using remove_cvref_t // NOLINT(readability-identifier-naming)
= typename remove_cvref<T>::type;
template<typename Fn> class function_ref;
template<typename Ret, typename ...Params>
class function_ref<Ret(Params...)> {
Ret (*callback)(intptr_t callable, Params ...params) = nullptr;
intptr_t callable;
template<typename Callable>
static Ret callback_fn(intptr_t callable, Params ...params) {
return (*reinterpret_cast<Callable*>(callable))(
std::forward<Params>(params)...);
}
public:
function_ref() = default;
function_ref(std::nullptr_t) {}
template <typename Callable>
function_ref(
Callable &&callable,
// This is not the copy-constructor.
std::enable_if_t<!std::is_same<remove_cvref_t<Callable>,
function_ref>::value> * = nullptr,
// Functor must be callable and return a suitable type.
std::enable_if_t<std::is_void<Ret>::value ||
std::is_convertible<decltype(std::declval<Callable>()(
std::declval<Params>()...)),
Ret>::value> * = nullptr)
: callback(callback_fn<typename std::remove_reference<Callable>::type>),
callable(reinterpret_cast<intptr_t>(&callable)) {}
Ret operator()(Params ...params) const {
return callback(callable, std::forward<Params>(params)...);
}
explicit operator bool() const { return callback; }
};
struct Data{
int a;
int b;
};
void test_callback(function_ref<void(Data&)> callback){
Data data={1,3};
callback(data);
}
void test_std_fun(std::function<void(Data&)> callback){
Data data={12,3};
callback(data);
}
int main(){
int a=123;
auto callback=[&](Data &data){
std::cout<<a<<" "<<data.a<<std::endl;
};
test_callback(callback);
test_std_fun(callback);
std::cout<<"hello world"<<std::endl;
}
Reference:
[1]c++ std::function