-/// An efficient, type-erasing, non-owning reference to a callable. This is
-/// intended for use as the type of a function parameter that is not used
-/// after the function in question returns.
-///
-/// This class does not own the callable, so it is not in general safe to store
-/// a function_ref.
-template<typename Fn> class function_ref;
-
-#if LLVM_HAS_VARIADIC_TEMPLATES
-
-template<typename Ret, typename ...Params>
-class function_ref<Ret(Params...)> {
- Ret (*callback)(void *callable, Params ...params);
- void *callable;
-
- template<typename Callable>
- static Ret callback_fn(void *callable, Params ...params) {
- return reinterpret_cast<Callable&>(*callable)(
- std::forward<Params>(params)...);
- }
-
-public:
- template<typename Callable>
- function_ref(Callable &&callable)
- : callback(callback_fn<Callable>),
- callable(reinterpret_cast<void *>(&callable)) {}
- Ret operator()(Params ...params) const {
- return callback(callable, std::forward<Params>(params)...);
- }
-};
-
-#else
-
-template<typename Ret>
-class function_ref<Ret()> {
- Ret (*callback)(void *callable);
- void *callable;
-
- template<typename Callable>
- static Ret callback_fn(void *callable) {
- return reinterpret_cast<Callable&>(*callable)();
- }
-
-public:
- template<typename Callable>
- function_ref(Callable &&callable)
- : callback(callback_fn<Callable>),
- callable(reinterpret_cast<void *>(&callable)) {}
- Ret operator()() const { return callback(callable); }
-};
-
-template<typename Ret, typename Param1>
-class function_ref<Ret(Param1)> {
- Ret (*callback)(void *callable, Param1 param1);
- void *callable;
-
- template<typename Callable>
- static Ret callback_fn(void *callable, Param1 param1) {
- return reinterpret_cast<Callable&>(*callable)(
- std::forward<Param1>(param1));
- }
-
-public:
- template<typename Callable>
- function_ref(Callable &&callable)
- : callback(callback_fn<Callable>),
- callable(reinterpret_cast<void *>(&callable)) {}
- Ret operator()(Param1 param1) {
- return callback(callable, std::forward<Param1>(param1));
- }
-};
-
-template<typename Ret, typename Param1, typename Param2>
-class function_ref<Ret(Param1, Param2)> {
- Ret (*callback)(void *callable, Param1 param1, Param2 param2);
- void *callable;
-
- template<typename Callable>
- static Ret callback_fn(void *callable, Param1 param1, Param2 param2) {
- return reinterpret_cast<Callable&>(*callable)(
- std::forward<Param1>(param1),
- std::forward<Param2>(param2));
- }
-
-public:
- template<typename Callable>
- function_ref(Callable &&callable)
- : callback(callback_fn<Callable>),
- callable(reinterpret_cast<void *>(&callable)) {}
- Ret operator()(Param1 param1, Param2 param2) {
- return callback(callable,
- std::forward<Param1>(param1),
- std::forward<Param2>(param2));
- }
-};
-
-template<typename Ret, typename Param1, typename Param2, typename Param3>
-class function_ref<Ret(Param1, Param2, Param3)> {
- Ret (*callback)(void *callable, Param1 param1, Param2 param2, Param3 param3);
- void *callable;
-
- template<typename Callable>
- static Ret callback_fn(void *callable, Param1 param1, Param2 param2,
- Param3 param3) {
- return reinterpret_cast<Callable&>(*callable)(
- std::forward<Param1>(param1),
- std::forward<Param2>(param2),
- std::forward<Param3>(param3));
- }
-
-public:
- template<typename Callable>
- function_ref(Callable &&callable)
- : callback(callback_fn<Callable>),
- callable(reinterpret_cast<void *>(&callable)) {}
- Ret operator()(Param1 param1, Param2 param2, Param3 param3) {
- return callback(callable,
- std::forward<Param1>(param1),
- std::forward<Param2>(param2),
- std::forward<Param3>(param3));
- }
-};
-
-#endif
-