1*700637cbSDimitry Andric //===----- unique_function.h - moveable type-erasing function ---*- C++ -*-===// 2*700637cbSDimitry Andric // 3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*700637cbSDimitry Andric // 7*700637cbSDimitry Andric //===----------------------------------------------------------------------===// 8*700637cbSDimitry Andric /// 9*700637cbSDimitry Andric /// unique_function works like std::function, but supports move-only callable 10*700637cbSDimitry Andric /// objects. 11*700637cbSDimitry Andric /// 12*700637cbSDimitry Andric /// TODO: Use LLVM's unique_function (llvm/include/llvm/ADT/FunctionExtras.h), 13*700637cbSDimitry Andric /// which uses some extra inline storage to avoid heap allocations for 14*700637cbSDimitry Andric /// small objects. Using LLVM's unique_function will require first 15*700637cbSDimitry Andric /// porting some other utilities like PointerIntPair, PointerUnion, and 16*700637cbSDimitry Andric /// PointerLikeTypeTraits. (These are likely to be independently useful 17*700637cbSDimitry Andric /// in the orc runtime, so porting will have additional benefits). 18*700637cbSDimitry Andric /// 19*700637cbSDimitry Andric //===----------------------------------------------------------------------===// 20*700637cbSDimitry Andric 21*700637cbSDimitry Andric #ifndef ORC_RT_UNIQUE_FUNCTION_H 22*700637cbSDimitry Andric #define ORC_RT_UNIQUE_FUNCTION_H 23*700637cbSDimitry Andric 24*700637cbSDimitry Andric #include <memory> 25*700637cbSDimitry Andric 26*700637cbSDimitry Andric namespace orc_rt { 27*700637cbSDimitry Andric 28*700637cbSDimitry Andric namespace unique_function_detail { 29*700637cbSDimitry Andric 30*700637cbSDimitry Andric template <typename RetT, typename... ArgTs> class Callable { 31*700637cbSDimitry Andric public: 32*700637cbSDimitry Andric virtual ~Callable() = default; 33*700637cbSDimitry Andric virtual RetT call(ArgTs &&...Args) = 0; 34*700637cbSDimitry Andric }; 35*700637cbSDimitry Andric 36*700637cbSDimitry Andric template <typename CallableT, typename RetT, typename... ArgTs> 37*700637cbSDimitry Andric class CallableImpl : public Callable<RetT, ArgTs...> { 38*700637cbSDimitry Andric public: CallableImpl(CallableT && Callable)39*700637cbSDimitry Andric CallableImpl(CallableT &&Callable) : Callable(std::move(Callable)) {} call(ArgTs &&...Args)40*700637cbSDimitry Andric RetT call(ArgTs &&...Args) override { 41*700637cbSDimitry Andric return Callable(std::forward<ArgTs>(Args)...); 42*700637cbSDimitry Andric } 43*700637cbSDimitry Andric 44*700637cbSDimitry Andric private: 45*700637cbSDimitry Andric CallableT Callable; 46*700637cbSDimitry Andric }; 47*700637cbSDimitry Andric 48*700637cbSDimitry Andric } // namespace unique_function_detail 49*700637cbSDimitry Andric 50*700637cbSDimitry Andric template <typename FnT> class unique_function; 51*700637cbSDimitry Andric 52*700637cbSDimitry Andric template <typename RetT, typename... ArgTs> 53*700637cbSDimitry Andric class unique_function<RetT(ArgTs...)> { 54*700637cbSDimitry Andric public: 55*700637cbSDimitry Andric unique_function() = default; unique_function(std::nullptr_t)56*700637cbSDimitry Andric unique_function(std::nullptr_t) {} 57*700637cbSDimitry Andric unique_function(unique_function &&) = default; 58*700637cbSDimitry Andric unique_function(const unique_function &&) = delete; 59*700637cbSDimitry Andric unique_function &operator=(unique_function &&) = default; 60*700637cbSDimitry Andric unique_function &operator=(const unique_function &&) = delete; 61*700637cbSDimitry Andric 62*700637cbSDimitry Andric template <typename CallableT> unique_function(CallableT && Callable)63*700637cbSDimitry Andric unique_function(CallableT &&Callable) 64*700637cbSDimitry Andric : C(std::make_unique< 65*700637cbSDimitry Andric unique_function_detail::CallableImpl<CallableT, RetT, ArgTs...>>( 66*700637cbSDimitry Andric std::forward<CallableT>(Callable))) {} 67*700637cbSDimitry Andric operator()68*700637cbSDimitry Andric RetT operator()(ArgTs... Params) { 69*700637cbSDimitry Andric return C->call(std::forward<ArgTs>(Params)...); 70*700637cbSDimitry Andric } 71*700637cbSDimitry Andric 72*700637cbSDimitry Andric explicit operator bool() const { return !!C; } 73*700637cbSDimitry Andric 74*700637cbSDimitry Andric private: 75*700637cbSDimitry Andric std::unique_ptr<unique_function_detail::Callable<RetT, ArgTs...>> C; 76*700637cbSDimitry Andric }; 77*700637cbSDimitry Andric 78*700637cbSDimitry Andric } // namespace orc_rt 79*700637cbSDimitry Andric 80*700637cbSDimitry Andric #endif // ORC_RT_UNIQUE_FUNCTION_H 81