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