1 //===- llvm/ADT/STLFunctionalExtras.h - Extras for <functional> -*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains some extension to <functional>. 10 // 11 // No library is required when using these functions. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_ADT_STLFUNCTIONALEXTRAS_H 16 #define LLVM_ADT_STLFUNCTIONALEXTRAS_H 17 18 #include "llvm/ADT/STLForwardCompat.h" 19 20 #include <cstdint> 21 #include <type_traits> 22 #include <utility> 23 24 namespace llvm { 25 26 //===----------------------------------------------------------------------===// 27 // Extra additions to <functional> 28 //===----------------------------------------------------------------------===// 29 30 /// An efficient, type-erasing, non-owning reference to a callable. This is 31 /// intended for use as the type of a function parameter that is not used 32 /// after the function in question returns. 33 /// 34 /// This class does not own the callable, so it is not in general safe to store 35 /// a function_ref. 36 template<typename Fn> class function_ref; 37 38 template<typename Ret, typename ...Params> 39 class function_ref<Ret(Params...)> { 40 Ret (*callback)(intptr_t callable, Params ...params) = nullptr; 41 intptr_t callable; 42 43 template<typename Callable> callback_fn(intptr_t callable,Params...params)44 static Ret callback_fn(intptr_t callable, Params ...params) { 45 return (*reinterpret_cast<Callable*>(callable))( 46 std::forward<Params>(params)...); 47 } 48 49 public: 50 function_ref() = default; function_ref(std::nullptr_t)51 function_ref(std::nullptr_t) {} 52 53 template <typename Callable> 54 function_ref( 55 Callable &&callable, 56 // This is not the copy-constructor. 57 std::enable_if_t<!std::is_same<remove_cvref_t<Callable>, 58 function_ref>::value> * = nullptr, 59 // Functor must be callable and return a suitable type. 60 std::enable_if_t<std::is_void<Ret>::value || 61 std::is_convertible<decltype(std::declval<Callable>()( 62 std::declval<Params>()...)), 63 Ret>::value> * = nullptr) callback(callback_fn<std::remove_reference_t<Callable>>)64 : callback(callback_fn<std::remove_reference_t<Callable>>), 65 callable(reinterpret_cast<intptr_t>(&callable)) {} 66 operator()67 Ret operator()(Params ...params) const { 68 return callback(callable, std::forward<Params>(params)...); 69 } 70 71 explicit operator bool() const { return callback; } 72 }; 73 74 } // end namespace llvm 75 76 #endif // LLVM_ADT_STLFUNCTIONALEXTRAS_H 77