1 //===-- Self contained functional header ------------------------*- 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 #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_FUNCTIONAL_H 10 #define LLVM_LIBC_SRC___SUPPORT_CPP_FUNCTIONAL_H 11 12 #include "src/__support/CPP/type_traits/enable_if.h" 13 #include "src/__support/CPP/type_traits/is_convertible.h" 14 #include "src/__support/CPP/type_traits/is_same.h" 15 #include "src/__support/CPP/type_traits/is_void.h" 16 #include "src/__support/CPP/type_traits/remove_cvref.h" 17 #include "src/__support/CPP/type_traits/remove_reference.h" 18 #include "src/__support/CPP/utility/forward.h" 19 #include "src/__support/macros/attributes.h" 20 #include "src/__support/macros/config.h" 21 22 #include <stdint.h> 23 24 namespace LIBC_NAMESPACE_DECL { 25 namespace cpp { 26 27 /// A function type adapted from LLVM's function_ref. 28 /// This class does not own the callable, so it is not in general safe to 29 /// store a function. 30 template <typename Fn> class function; 31 32 template <typename Ret, typename... Params> class function<Ret(Params...)> { 33 Ret (*callback)(intptr_t callable, Params... params) = nullptr; 34 intptr_t callable; 35 36 template <typename Callable> callback_fn(intptr_t callable,Params...params)37 LIBC_INLINE static Ret callback_fn(intptr_t callable, Params... params) { 38 return (*reinterpret_cast<Callable *>(callable))( 39 cpp::forward<Params>(params)...); 40 } 41 42 public: 43 LIBC_INLINE function() = default; function(decltype (nullptr))44 LIBC_INLINE function(decltype(nullptr)) {} 45 LIBC_INLINE ~function() = default; 46 47 template <typename Callable> 48 LIBC_INLINE function( 49 Callable &&callable, 50 // This is not the copy-constructor. 51 enable_if_t<!cpp::is_same_v<remove_cvref_t<Callable>, function>> * = 52 nullptr, 53 // Functor must be callable and return a suitable type. 54 enable_if_t<cpp::is_void_v<Ret> || 55 cpp::is_convertible_v< 56 decltype(declval<Callable>()(declval<Params>()...)), Ret>> 57 * = nullptr) callback(callback_fn<cpp::remove_reference_t<Callable>>)58 : callback(callback_fn<cpp::remove_reference_t<Callable>>), 59 callable(reinterpret_cast<intptr_t>(&callable)) {} 60 operator()61 LIBC_INLINE Ret operator()(Params... params) const { 62 return callback(callable, cpp::forward<Params>(params)...); 63 } 64 65 LIBC_INLINE explicit operator bool() const { return callback; } 66 }; 67 68 } // namespace cpp 69 } // namespace LIBC_NAMESPACE_DECL 70 71 #endif // LLVM_LIBC_SRC___SUPPORT_CPP_FUNCTIONAL_H 72