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 #include "llvm/Support/Compiler.h" 20 21 #include <cstdint> 22 #include <type_traits> 23 #include <utility> 24 25 namespace llvm { 26 27 //===----------------------------------------------------------------------===// 28 // Extra additions to <functional> 29 //===----------------------------------------------------------------------===// 30 31 /// An efficient, type-erasing, non-owning reference to a callable. This is 32 /// intended for use as the type of a function parameter that is not used 33 /// after the function in question returns. 34 /// 35 /// This class does not own the callable, so it is not in general safe to store 36 /// a function_ref. 37 template<typename Fn> class function_ref; 38 39 template <typename Ret, typename... Params> 40 class LLVM_GSL_POINTER function_ref<Ret(Params...)> { 41 Ret (*callback)(intptr_t callable, Params ...params) = nullptr; 42 intptr_t callable; 43 44 template<typename Callable> 45 static Ret callback_fn(intptr_t callable, Params ...params) { 46 return (*reinterpret_cast<Callable*>(callable))( 47 std::forward<Params>(params)...); 48 } 49 50 public: 51 function_ref() = default; 52 function_ref(std::nullptr_t) {} 53 54 template <typename Callable> 55 function_ref( 56 Callable &&callable LLVM_LIFETIME_BOUND, 57 // This is not the copy-constructor. 58 std::enable_if_t<!std::is_same<remove_cvref_t<Callable>, 59 function_ref>::value> * = nullptr, 60 // Functor must be callable and return a suitable type. 61 std::enable_if_t<std::is_void<Ret>::value || 62 std::is_convertible<decltype(std::declval<Callable>()( 63 std::declval<Params>()...)), 64 Ret>::value> * = nullptr) 65 : callback(callback_fn<std::remove_reference_t<Callable>>), 66 callable(reinterpret_cast<intptr_t>(&callable)) {} 67 68 Ret operator()(Params ...params) const { 69 return callback(callable, std::forward<Params>(params)...); 70 } 71 72 explicit operator bool() const { return callback; } 73 74 bool operator==(const function_ref<Ret(Params...)> &Other) const { 75 return callable == Other.callable; 76 } 77 }; 78 79 } // end namespace llvm 80 81 #endif // LLVM_ADT_STLFUNCTIONALEXTRAS_H 82