1*38e8c45fSAndroid Build Coastguard Worker /* 2*38e8c45fSAndroid Build Coastguard Worker * Copyright 2022 The Android Open Source Project 3*38e8c45fSAndroid Build Coastguard Worker * 4*38e8c45fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*38e8c45fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*38e8c45fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*38e8c45fSAndroid Build Coastguard Worker * 8*38e8c45fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*38e8c45fSAndroid Build Coastguard Worker * 10*38e8c45fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*38e8c45fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*38e8c45fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*38e8c45fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*38e8c45fSAndroid Build Coastguard Worker * limitations under the License. 15*38e8c45fSAndroid Build Coastguard Worker */ 16*38e8c45fSAndroid Build Coastguard Worker 17*38e8c45fSAndroid Build Coastguard Worker #pragma once 18*38e8c45fSAndroid Build Coastguard Worker 19*38e8c45fSAndroid Build Coastguard Worker #include <cstddef> 20*38e8c45fSAndroid Build Coastguard Worker #include <functional> 21*38e8c45fSAndroid Build Coastguard Worker #include <type_traits> 22*38e8c45fSAndroid Build Coastguard Worker #include <utility> 23*38e8c45fSAndroid Build Coastguard Worker 24*38e8c45fSAndroid Build Coastguard Worker #include <ftl/details/function.h> 25*38e8c45fSAndroid Build Coastguard Worker 26*38e8c45fSAndroid Build Coastguard Worker namespace android::ftl { 27*38e8c45fSAndroid Build Coastguard Worker 28*38e8c45fSAndroid Build Coastguard Worker // ftl::Function<F, N> is a container for function object, and can mostly be used in place of 29*38e8c45fSAndroid Build Coastguard Worker // std::function<F>. 30*38e8c45fSAndroid Build Coastguard Worker // 31*38e8c45fSAndroid Build Coastguard Worker // Unlike std::function<F>, a ftl::Function<F, N>: 32*38e8c45fSAndroid Build Coastguard Worker // 33*38e8c45fSAndroid Build Coastguard Worker // * Uses a static amount of memory (controlled by N), and never any dynamic allocation. 34*38e8c45fSAndroid Build Coastguard Worker // * Satisfies the std::is_trivially_copyable<> trait. 35*38e8c45fSAndroid Build Coastguard Worker // * Satisfies the std::is_trivially_destructible<> trait. 36*38e8c45fSAndroid Build Coastguard Worker // 37*38e8c45fSAndroid Build Coastguard Worker // However those same limits are also required from the contained function object in turn. 38*38e8c45fSAndroid Build Coastguard Worker // 39*38e8c45fSAndroid Build Coastguard Worker // The size of a ftl::Function<F, N> is guaranteed to be: 40*38e8c45fSAndroid Build Coastguard Worker // 41*38e8c45fSAndroid Build Coastguard Worker // sizeof(std::intptr_t) * (N + 2) 42*38e8c45fSAndroid Build Coastguard Worker // 43*38e8c45fSAndroid Build Coastguard Worker // A ftl::Function<F, N> can always be implicitly converted to a larger size ftl::Function<F, M>. 44*38e8c45fSAndroid Build Coastguard Worker // Trying to convert the other way leads to a compilation error. 45*38e8c45fSAndroid Build Coastguard Worker // 46*38e8c45fSAndroid Build Coastguard Worker // A default-constructed ftl::Function is in an empty state. The operator bool() overload returns 47*38e8c45fSAndroid Build Coastguard Worker // false in this state. It is undefined behavior to attempt to invoke the function in this state. 48*38e8c45fSAndroid Build Coastguard Worker // 49*38e8c45fSAndroid Build Coastguard Worker // The ftl::Function<F, N> can also be constructed or assigned from ftl::no_op. This sets up the 50*38e8c45fSAndroid Build Coastguard Worker // ftl::Function to be non-empty, with a function that when called does nothing except 51*38e8c45fSAndroid Build Coastguard Worker // default-constructs a return value. 52*38e8c45fSAndroid Build Coastguard Worker // 53*38e8c45fSAndroid Build Coastguard Worker // The ftl::make_function() helpers construct a ftl::Function<F, N>, including deducing the 54*38e8c45fSAndroid Build Coastguard Worker // values of F and N from the arguments it is given. 55*38e8c45fSAndroid Build Coastguard Worker // 56*38e8c45fSAndroid Build Coastguard Worker // The static ftl::Function<F, N>::make() helpers construct a ftl::Function<F, N> without that 57*38e8c45fSAndroid Build Coastguard Worker // deduction, and also allow for implicit argument conversion if the target being called needs them. 58*38e8c45fSAndroid Build Coastguard Worker // 59*38e8c45fSAndroid Build Coastguard Worker // The construction helpers allow any of the following types of functions to be stored: 60*38e8c45fSAndroid Build Coastguard Worker // 61*38e8c45fSAndroid Build Coastguard Worker // * Any SMALL function object (as defined by the C++ Standard), such as a lambda with a small 62*38e8c45fSAndroid Build Coastguard Worker // capture, or other "functor". The requirements are: 63*38e8c45fSAndroid Build Coastguard Worker // 64*38e8c45fSAndroid Build Coastguard Worker // 1) The function object must be trivial to destroy (in fact, the destructor will never 65*38e8c45fSAndroid Build Coastguard Worker // actually be called once copied to the internal storage). 66*38e8c45fSAndroid Build Coastguard Worker // 2) The function object must be trivial to copy (the raw bytes will be copied as the 67*38e8c45fSAndroid Build Coastguard Worker // ftl::Function<F, N> is copied/moved). 68*38e8c45fSAndroid Build Coastguard Worker // 3) The size of the function object cannot be larger than sizeof(std::intptr_t) * (N + 1), 69*38e8c45fSAndroid Build Coastguard Worker // and it cannot require stricter alignment than alignof(std::intptr_t). 70*38e8c45fSAndroid Build Coastguard Worker // 71*38e8c45fSAndroid Build Coastguard Worker // With the default of N=0, a lambda can only capture a single pointer-sized argument. This is 72*38e8c45fSAndroid Build Coastguard Worker // enough to capture `this`, which is why N=0 is the default. 73*38e8c45fSAndroid Build Coastguard Worker // 74*38e8c45fSAndroid Build Coastguard Worker // * A member function, with the address passed as the template value argument to the construction 75*38e8c45fSAndroid Build Coastguard Worker // helper function, along with the instance pointer needed to invoke it passed as an ordinary 76*38e8c45fSAndroid Build Coastguard Worker // argument. 77*38e8c45fSAndroid Build Coastguard Worker // 78*38e8c45fSAndroid Build Coastguard Worker // ftl::make_function<&Class::member_function>(this); 79*38e8c45fSAndroid Build Coastguard Worker // 80*38e8c45fSAndroid Build Coastguard Worker // Note that the indicated member function will be invoked non-virtually. If you need it to be 81*38e8c45fSAndroid Build Coastguard Worker // invoked virtually, you should invoke it yourself with a small lambda like so: 82*38e8c45fSAndroid Build Coastguard Worker // 83*38e8c45fSAndroid Build Coastguard Worker // ftl::function([this] { virtual_member_function(); }); 84*38e8c45fSAndroid Build Coastguard Worker // 85*38e8c45fSAndroid Build Coastguard Worker // * An ordinary function ("free function"), with the address of the function passed as a template 86*38e8c45fSAndroid Build Coastguard Worker // value argument. 87*38e8c45fSAndroid Build Coastguard Worker // 88*38e8c45fSAndroid Build Coastguard Worker // ftl::make_function<&std::atoi>(); 89*38e8c45fSAndroid Build Coastguard Worker // 90*38e8c45fSAndroid Build Coastguard Worker // As with the member function helper, as the function is known at compile time, it will be called 91*38e8c45fSAndroid Build Coastguard Worker // directly. 92*38e8c45fSAndroid Build Coastguard Worker // 93*38e8c45fSAndroid Build Coastguard Worker // Example usage: 94*38e8c45fSAndroid Build Coastguard Worker // 95*38e8c45fSAndroid Build Coastguard Worker // class MyClass { 96*38e8c45fSAndroid Build Coastguard Worker // public: 97*38e8c45fSAndroid Build Coastguard Worker // void on_event() const {} 98*38e8c45fSAndroid Build Coastguard Worker // int on_string(int*, std::string_view) { return 1; } 99*38e8c45fSAndroid Build Coastguard Worker // 100*38e8c45fSAndroid Build Coastguard Worker // auto get_function() { 101*38e8c45fSAndroid Build Coastguard Worker // return ftl::function([this] { on_event(); }); 102*38e8c45fSAndroid Build Coastguard Worker // } 103*38e8c45fSAndroid Build Coastguard Worker // } cls; 104*38e8c45fSAndroid Build Coastguard Worker // 105*38e8c45fSAndroid Build Coastguard Worker // // A function container with no arguments, and returning no value. 106*38e8c45fSAndroid Build Coastguard Worker // ftl::Function<void()> f; 107*38e8c45fSAndroid Build Coastguard Worker // 108*38e8c45fSAndroid Build Coastguard Worker // // Construct a ftl::Function containing a small lambda. 109*38e8c45fSAndroid Build Coastguard Worker // f = cls.get_function(); 110*38e8c45fSAndroid Build Coastguard Worker // 111*38e8c45fSAndroid Build Coastguard Worker // // Construct a ftl::Function that calls `cls.on_event()`. 112*38e8c45fSAndroid Build Coastguard Worker // f = ftl::function<&MyClass::on_event>(&cls); 113*38e8c45fSAndroid Build Coastguard Worker // 114*38e8c45fSAndroid Build Coastguard Worker // // Create a do-nothing function. 115*38e8c45fSAndroid Build Coastguard Worker // f = ftl::no_op; 116*38e8c45fSAndroid Build Coastguard Worker // 117*38e8c45fSAndroid Build Coastguard Worker // // Invoke the contained function. 118*38e8c45fSAndroid Build Coastguard Worker // f(); 119*38e8c45fSAndroid Build Coastguard Worker // 120*38e8c45fSAndroid Build Coastguard Worker // // Also invokes it. 121*38e8c45fSAndroid Build Coastguard Worker // std::invoke(f); 122*38e8c45fSAndroid Build Coastguard Worker // 123*38e8c45fSAndroid Build Coastguard Worker // // Create a typedef to give a more meaningful name and bound the size. 124*38e8c45fSAndroid Build Coastguard Worker // using MyFunction = ftl::Function<int(std::string_view), 2>; 125*38e8c45fSAndroid Build Coastguard Worker // int* ptr = nullptr; 126*38e8c45fSAndroid Build Coastguard Worker // auto f1 = MyFunction::make( 127*38e8c45fSAndroid Build Coastguard Worker // [cls = &cls, ptr](std::string_view sv) { 128*38e8c45fSAndroid Build Coastguard Worker // return cls->on_string(ptr, sv); 129*38e8c45fSAndroid Build Coastguard Worker // }); 130*38e8c45fSAndroid Build Coastguard Worker // int r = f1("abc"sv); 131*38e8c45fSAndroid Build Coastguard Worker // 132*38e8c45fSAndroid Build Coastguard Worker // // Returns a default-constructed int (0). 133*38e8c45fSAndroid Build Coastguard Worker // f1 = ftl::no_op; 134*38e8c45fSAndroid Build Coastguard Worker // r = f1("abc"sv); 135*38e8c45fSAndroid Build Coastguard Worker // assert(r == 0); 136*38e8c45fSAndroid Build Coastguard Worker 137*38e8c45fSAndroid Build Coastguard Worker template <typename F, std::size_t N = 0> 138*38e8c45fSAndroid Build Coastguard Worker class Function; 139*38e8c45fSAndroid Build Coastguard Worker 140*38e8c45fSAndroid Build Coastguard Worker // Used to construct a Function that does nothing. 141*38e8c45fSAndroid Build Coastguard Worker struct NoOpTag {}; 142*38e8c45fSAndroid Build Coastguard Worker 143*38e8c45fSAndroid Build Coastguard Worker constexpr NoOpTag no_op; 144*38e8c45fSAndroid Build Coastguard Worker 145*38e8c45fSAndroid Build Coastguard Worker // Detects that a type is a `ftl::Function<F, N>` regardless of what `F` and `N` are. 146*38e8c45fSAndroid Build Coastguard Worker template <typename> 147*38e8c45fSAndroid Build Coastguard Worker struct is_function : public std::false_type {}; 148*38e8c45fSAndroid Build Coastguard Worker 149*38e8c45fSAndroid Build Coastguard Worker template <typename F, std::size_t N> 150*38e8c45fSAndroid Build Coastguard Worker struct is_function<Function<F, N>> : public std::true_type {}; 151*38e8c45fSAndroid Build Coastguard Worker 152*38e8c45fSAndroid Build Coastguard Worker template <typename T> 153*38e8c45fSAndroid Build Coastguard Worker constexpr bool is_function_v = is_function<T>::value; 154*38e8c45fSAndroid Build Coastguard Worker 155*38e8c45fSAndroid Build Coastguard Worker template <typename Ret, typename... Args, std::size_t N> 156*38e8c45fSAndroid Build Coastguard Worker class Function<Ret(Args...), N> final { 157*38e8c45fSAndroid Build Coastguard Worker // Enforce a valid size, with an arbitrary maximum allowed size for the container of 158*38e8c45fSAndroid Build Coastguard Worker // sizeof(std::intptr_t) * 16, though that maximum can be relaxed. 159*38e8c45fSAndroid Build Coastguard Worker static_assert(N <= details::kFunctionMaximumN); 160*38e8c45fSAndroid Build Coastguard Worker 161*38e8c45fSAndroid Build Coastguard Worker using OpaqueStorageTraits = details::function_opaque_storage<N>; 162*38e8c45fSAndroid Build Coastguard Worker 163*38e8c45fSAndroid Build Coastguard Worker public: 164*38e8c45fSAndroid Build Coastguard Worker // Defining result_type allows ftl::Function to be substituted for std::function. 165*38e8c45fSAndroid Build Coastguard Worker using result_type = Ret; 166*38e8c45fSAndroid Build Coastguard Worker 167*38e8c45fSAndroid Build Coastguard Worker // Constructs an empty ftl::Function. 168*38e8c45fSAndroid Build Coastguard Worker Function() = default; 169*38e8c45fSAndroid Build Coastguard Worker 170*38e8c45fSAndroid Build Coastguard Worker // Constructing or assigning from nullptr_t also creates an empty ftl::Function. 171*38e8c45fSAndroid Build Coastguard Worker Function(std::nullptr_t) {} 172*38e8c45fSAndroid Build Coastguard Worker Function& operator=(std::nullptr_t) { return *this = Function(nullptr); } 173*38e8c45fSAndroid Build Coastguard Worker 174*38e8c45fSAndroid Build Coastguard Worker // Constructing from NoOpTag sets up a a special no-op function which is valid to call, and which 175*38e8c45fSAndroid Build Coastguard Worker // returns a default constructed return value. 176*38e8c45fSAndroid Build Coastguard Worker Function(NoOpTag) : function_(details::bind_opaque_no_op<Ret, Args...>()) {} 177*38e8c45fSAndroid Build Coastguard Worker Function& operator=(NoOpTag) { return *this = Function(no_op); } 178*38e8c45fSAndroid Build Coastguard Worker 179*38e8c45fSAndroid Build Coastguard Worker // Constructing/assigning from a function object stores a copy of that function object, however: 180*38e8c45fSAndroid Build Coastguard Worker // * It must be trivially copyable, as the implementation makes a copy with memcpy(). 181*38e8c45fSAndroid Build Coastguard Worker // * It must be trivially destructible, as the implementation doesn't destroy the copy! 182*38e8c45fSAndroid Build Coastguard Worker // * It must fit in the limited internal storage, which enforces size/alignment restrictions. 183*38e8c45fSAndroid Build Coastguard Worker 184*38e8c45fSAndroid Build Coastguard Worker template <typename F, typename = std::enable_if_t<std::is_invocable_r_v<Ret, F, Args...>>> 185*38e8c45fSAndroid Build Coastguard Worker Function(const F& f) 186*38e8c45fSAndroid Build Coastguard Worker : opaque_(OpaqueStorageTraits::opaque_copy(f)), 187*38e8c45fSAndroid Build Coastguard Worker function_(details::bind_opaque_function_object<F, Ret, Args...>(f)) {} 188*38e8c45fSAndroid Build Coastguard Worker 189*38e8c45fSAndroid Build Coastguard Worker template <typename F, typename = std::enable_if_t<std::is_invocable_r_v<Ret, F, Args...>>> 190*38e8c45fSAndroid Build Coastguard Worker Function& operator=(const F& f) noexcept { 191*38e8c45fSAndroid Build Coastguard Worker return *this = Function{OpaqueStorageTraits::opaque_copy(f), 192*38e8c45fSAndroid Build Coastguard Worker details::bind_opaque_function_object<F, Ret, Args...>(f)}; 193*38e8c45fSAndroid Build Coastguard Worker } 194*38e8c45fSAndroid Build Coastguard Worker 195*38e8c45fSAndroid Build Coastguard Worker // Constructing/assigning from a smaller ftl::Function is allowed, but not anything else. 196*38e8c45fSAndroid Build Coastguard Worker 197*38e8c45fSAndroid Build Coastguard Worker template <std::size_t M> 198*38e8c45fSAndroid Build Coastguard Worker Function(const Function<Ret(Args...), M>& other) 199*38e8c45fSAndroid Build Coastguard Worker : opaque_{OpaqueStorageTraits::opaque_copy(other.opaque_)}, function_(other.function_) {} 200*38e8c45fSAndroid Build Coastguard Worker 201*38e8c45fSAndroid Build Coastguard Worker template <std::size_t M> 202*38e8c45fSAndroid Build Coastguard Worker auto& operator=(const Function<Ret(Args...), M>& other) { 203*38e8c45fSAndroid Build Coastguard Worker return *this = Function{OpaqueStorageTraits::opaque_copy(other.opaque_), other.function_}; 204*38e8c45fSAndroid Build Coastguard Worker } 205*38e8c45fSAndroid Build Coastguard Worker 206*38e8c45fSAndroid Build Coastguard Worker // Returns true if a function is set. 207*38e8c45fSAndroid Build Coastguard Worker explicit operator bool() const { return function_ != nullptr; } 208*38e8c45fSAndroid Build Coastguard Worker 209*38e8c45fSAndroid Build Coastguard Worker // Checks if the other function has the same contents as this one. 210*38e8c45fSAndroid Build Coastguard Worker bool operator==(const Function& other) const { 211*38e8c45fSAndroid Build Coastguard Worker return other.opaque_ == opaque_ && other.function_ == function_; 212*38e8c45fSAndroid Build Coastguard Worker } 213*38e8c45fSAndroid Build Coastguard Worker bool operator!=(const Function& other) const { return !operator==(other); } 214*38e8c45fSAndroid Build Coastguard Worker 215*38e8c45fSAndroid Build Coastguard Worker // Alternative way of testing for a function being set. 216*38e8c45fSAndroid Build Coastguard Worker bool operator==(std::nullptr_t) const { return function_ == nullptr; } 217*38e8c45fSAndroid Build Coastguard Worker bool operator!=(std::nullptr_t) const { return function_ != nullptr; } 218*38e8c45fSAndroid Build Coastguard Worker 219*38e8c45fSAndroid Build Coastguard Worker // Invokes the function. 220*38e8c45fSAndroid Build Coastguard Worker Ret operator()(Args... args) const { 221*38e8c45fSAndroid Build Coastguard Worker return std::invoke(function_, opaque_.data(), std::forward<Args>(args)...); 222*38e8c45fSAndroid Build Coastguard Worker } 223*38e8c45fSAndroid Build Coastguard Worker 224*38e8c45fSAndroid Build Coastguard Worker // Creation helper for function objects, such as lambdas. 225*38e8c45fSAndroid Build Coastguard Worker template <typename F> 226*38e8c45fSAndroid Build Coastguard Worker static auto make(const F& f) -> decltype(Function{f}) { 227*38e8c45fSAndroid Build Coastguard Worker return Function{f}; 228*38e8c45fSAndroid Build Coastguard Worker } 229*38e8c45fSAndroid Build Coastguard Worker 230*38e8c45fSAndroid Build Coastguard Worker // Creation helper for a class pointer and a compile-time chosen member function to call. 231*38e8c45fSAndroid Build Coastguard Worker template <auto MemberFunction, typename Class> 232*38e8c45fSAndroid Build Coastguard Worker static auto make(Class* instance) -> decltype(Function{ 233*38e8c45fSAndroid Build Coastguard Worker details::bind_member_function<MemberFunction>(instance, 234*38e8c45fSAndroid Build Coastguard Worker static_cast<Ret (*)(Args...)>(nullptr))}) { 235*38e8c45fSAndroid Build Coastguard Worker return Function{details::bind_member_function<MemberFunction>( 236*38e8c45fSAndroid Build Coastguard Worker instance, static_cast<Ret (*)(Args...)>(nullptr))}; 237*38e8c45fSAndroid Build Coastguard Worker } 238*38e8c45fSAndroid Build Coastguard Worker 239*38e8c45fSAndroid Build Coastguard Worker // Creation helper for a compile-time chosen free function to call. 240*38e8c45fSAndroid Build Coastguard Worker template <auto FreeFunction> 241*38e8c45fSAndroid Build Coastguard Worker static auto make() -> decltype(Function{ 242*38e8c45fSAndroid Build Coastguard Worker details::bind_free_function<FreeFunction>(static_cast<Ret (*)(Args...)>(nullptr))}) { 243*38e8c45fSAndroid Build Coastguard Worker return Function{ 244*38e8c45fSAndroid Build Coastguard Worker details::bind_free_function<FreeFunction>(static_cast<Ret (*)(Args...)>(nullptr))}; 245*38e8c45fSAndroid Build Coastguard Worker } 246*38e8c45fSAndroid Build Coastguard Worker 247*38e8c45fSAndroid Build Coastguard Worker private: 248*38e8c45fSAndroid Build Coastguard Worker // Needed so a Function<F, M> can be converted to a Function<F, N>. 249*38e8c45fSAndroid Build Coastguard Worker template <typename, std::size_t> 250*38e8c45fSAndroid Build Coastguard Worker friend class Function; 251*38e8c45fSAndroid Build Coastguard Worker 252*38e8c45fSAndroid Build Coastguard Worker // The function pointer type of function stored in `function_`. The first argument is always 253*38e8c45fSAndroid Build Coastguard Worker // `&opaque_`. 254*38e8c45fSAndroid Build Coastguard Worker using StoredFunction = Ret(void*, Args...); 255*38e8c45fSAndroid Build Coastguard Worker 256*38e8c45fSAndroid Build Coastguard Worker // The type of the opaque storage, used to hold an appropriate function object. 257*38e8c45fSAndroid Build Coastguard Worker // The type stored here is ONLY known to the StoredFunction. 258*38e8c45fSAndroid Build Coastguard Worker // We always use at least one std::intptr_t worth of storage, and always a multiple of that size. 259*38e8c45fSAndroid Build Coastguard Worker using OpaqueStorage = typename OpaqueStorageTraits::type; 260*38e8c45fSAndroid Build Coastguard Worker 261*38e8c45fSAndroid Build Coastguard Worker // Internal constructor for creating from a raw opaque blob + function pointer. 262*38e8c45fSAndroid Build Coastguard Worker Function(const OpaqueStorage& opaque, StoredFunction* function) 263*38e8c45fSAndroid Build Coastguard Worker : opaque_(opaque), function_(function) {} 264*38e8c45fSAndroid Build Coastguard Worker 265*38e8c45fSAndroid Build Coastguard Worker // Note: `mutable` so that `operator() const` can use it. 266*38e8c45fSAndroid Build Coastguard Worker mutable OpaqueStorage opaque_{}; 267*38e8c45fSAndroid Build Coastguard Worker StoredFunction* function_{nullptr}; 268*38e8c45fSAndroid Build Coastguard Worker }; 269*38e8c45fSAndroid Build Coastguard Worker 270*38e8c45fSAndroid Build Coastguard Worker // Makes a ftl::Function given a function object `F`. 271*38e8c45fSAndroid Build Coastguard Worker template <typename F, typename T = details::function_traits<F>> 272*38e8c45fSAndroid Build Coastguard Worker Function(const F&) -> Function<typename T::type, T::size>; 273*38e8c45fSAndroid Build Coastguard Worker 274*38e8c45fSAndroid Build Coastguard Worker template <typename F> 275*38e8c45fSAndroid Build Coastguard Worker auto make_function(const F& f) -> decltype(Function{f}) { 276*38e8c45fSAndroid Build Coastguard Worker return Function{f}; 277*38e8c45fSAndroid Build Coastguard Worker } 278*38e8c45fSAndroid Build Coastguard Worker 279*38e8c45fSAndroid Build Coastguard Worker // Makes a ftl::Function given a `MemberFunction` and a instance pointer to the associated `Class`. 280*38e8c45fSAndroid Build Coastguard Worker template <auto MemberFunction, typename Class> 281*38e8c45fSAndroid Build Coastguard Worker auto make_function(Class* instance) 282*38e8c45fSAndroid Build Coastguard Worker -> decltype(Function{details::bind_member_function<MemberFunction>( 283*38e8c45fSAndroid Build Coastguard Worker instance, 284*38e8c45fSAndroid Build Coastguard Worker static_cast<details::remove_member_function_pointer_t<MemberFunction>*>(nullptr))}) { 285*38e8c45fSAndroid Build Coastguard Worker return Function{details::bind_member_function<MemberFunction>( 286*38e8c45fSAndroid Build Coastguard Worker instance, static_cast<details::remove_member_function_pointer_t<MemberFunction>*>(nullptr))}; 287*38e8c45fSAndroid Build Coastguard Worker } 288*38e8c45fSAndroid Build Coastguard Worker 289*38e8c45fSAndroid Build Coastguard Worker // Makes a ftl::Function given an ordinary free function. 290*38e8c45fSAndroid Build Coastguard Worker template <auto FreeFunction> 291*38e8c45fSAndroid Build Coastguard Worker auto make_function() -> decltype(Function{ 292*38e8c45fSAndroid Build Coastguard Worker details::bind_free_function<FreeFunction>(static_cast<decltype(FreeFunction)>(nullptr))}) { 293*38e8c45fSAndroid Build Coastguard Worker return Function{ 294*38e8c45fSAndroid Build Coastguard Worker details::bind_free_function<FreeFunction>(static_cast<decltype(FreeFunction)>(nullptr))}; 295*38e8c45fSAndroid Build Coastguard Worker } 296*38e8c45fSAndroid Build Coastguard Worker 297*38e8c45fSAndroid Build Coastguard Worker } // namespace android::ftl 298