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 21 #include <stdint.h> 22 23 namespace LIBC_NAMESPACE { 24 namespace cpp { 25 26 /// A function type adapted from LLVM's function_ref. 27 /// This class does not own the callable, so it is not in general safe to 28 /// store a function. 29 template <typename Fn> class function; 30 31 template <typename Ret, typename... Params> class function<Ret(Params...)> { 32 Ret (*callback)(intptr_t callable, Params... params) = nullptr; 33 intptr_t callable; 34 35 template <typename Callable> callback_fn(intptr_t callable,Params...params)36 LIBC_INLINE static Ret callback_fn(intptr_t callable, Params... params) { 37 return (*reinterpret_cast<Callable *>(callable))( 38 cpp::forward<Params>(params)...); 39 } 40 41 public: 42 LIBC_INLINE function() = default; function(decltype (nullptr))43 LIBC_INLINE function(decltype(nullptr)) {} 44 LIBC_INLINE ~function() = default; 45 46 template <typename Callable> 47 LIBC_INLINE function( 48 Callable &&callable, 49 // This is not the copy-constructor. 50 enable_if_t<!cpp::is_same_v<remove_cvref_t<Callable>, function>> * = 51 nullptr, 52 // Functor must be callable and return a suitable type. 53 enable_if_t<cpp::is_void_v<Ret> || 54 cpp::is_convertible_v< 55 decltype(declval<Callable>()(declval<Params>()...)), Ret>> 56 * = nullptr) callback(callback_fn<cpp::remove_reference_t<Callable>>)57 : callback(callback_fn<cpp::remove_reference_t<Callable>>), 58 callable(reinterpret_cast<intptr_t>(&callable)) {} 59 operator()60 LIBC_INLINE Ret operator()(Params... params) const { 61 return callback(callable, cpp::forward<Params>(params)...); 62 } 63 64 LIBC_INLINE explicit operator bool() const { return callback; } 65 }; 66 67 } // namespace cpp 68 } // namespace LIBC_NAMESPACE 69 70 #endif // LLVM_LIBC_SRC___SUPPORT_CPP_FUNCTIONAL_H 71