1 // Copyright 2022 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_FUNCTIONAL_FUNCTION_REF_H_ 6 #define BASE_FUNCTIONAL_FUNCTION_REF_H_ 7 8 #include <type_traits> 9 #include <utility> 10 11 #include "base/functional/bind_internal.h" 12 #include "third_party/abseil-cpp/absl/base/attributes.h" 13 #include "third_party/abseil-cpp/absl/functional/function_ref.h" 14 15 namespace base { 16 17 template <typename Signature> 18 class FunctionRef; 19 20 // A non-owning reference to any invocable object (e.g. function pointer, method 21 // pointer, functor, lambda, et cetera) suitable for use as a type-erased 22 // argument to ForEach-style functions or other visitor patterns that: 23 // 24 // - do not need to copy or take ownership of the argument 25 // - synchronously call the invocable that was passed as an argument 26 // 27 // `base::FunctionRef` makes no heap allocations: it is trivially copyable and 28 // should be passed by value. 29 // 30 // `base::FunctionRef` has no null/empty state: a `base::FunctionRef` is always 31 // valid to invoke. 32 // 33 // The usual lifetime precautions for other non-owning references types (e.g. 34 // `base::StringPiece`, `base::span`) also apply to `base::FunctionRef`. 35 // `base::FunctionRef` should typically be used as an argument; returning a 36 // `base::FunctionRef` or storing a `base::FunctionRef` as a field is dangerous 37 // and likely to result in lifetime bugs. 38 // 39 // `base::RepeatingCallback` and `base::BindRepeating()` is another common way 40 // to represent type-erased invocable objects. In contrast, it requires a heap 41 // allocation and is not trivially copyable. It should be used when there are 42 // ownership requirements (e.g. partial application of arguments to a function 43 // stored for asynchronous execution). 44 // 45 // Note: `base::FunctionRef` is similar to `absl::FunctionRef<R(Args...)>`, but 46 // with stricter conversions between function types. Return type conversions are 47 // allowed (e.g. `int` -> `bool`, `Derived*` -> `Base*`); other than that, 48 // function parameter types must match exactly, and return values may not be 49 // silently discarded, e.g. `absl::FunctionRef` allows the following: 50 // 51 // // Silently discards `42`. 52 // [] (absl::FunctionRef<void()> r) { 53 // r(); 54 // }([] { return 42; }); 55 // 56 // But with `base::FunctionRef`: 57 // 58 // // Does not compile! 59 // [] (base::FunctionRef<void()> r) { 60 // r(); 61 // }([] { return 42; }); 62 template <typename R, typename... Args> 63 class FunctionRef<R(Args...)> { 64 private: 65 template <typename Functor, 66 typename FunctorReturnType = 67 typename internal::BindTypeHelper<Functor>::ReturnType, 68 typename FunctorArgsAsTypeList = 69 typename internal::BindTypeHelper<Functor>::RunParamsList> 70 using EnableIfCompatible = std::enable_if_t< 71 std::is_convertible_v<FunctorReturnType, R> && 72 std::is_same_v<FunctorArgsAsTypeList, internal::TypeList<Args...>>>; 73 74 public: 75 // `ABSL_ATTRIBUTE_LIFETIME_BOUND` is important since `FunctionRef` retains 76 // only a reference to `functor`, `functor` must outlive `this`. 77 template <typename Functor, typename = EnableIfCompatible<Functor>> 78 // NOLINTNEXTLINE(google-explicit-constructor) FunctionRef(const Functor & functor ABSL_ATTRIBUTE_LIFETIME_BOUND)79 FunctionRef(const Functor& functor ABSL_ATTRIBUTE_LIFETIME_BOUND) 80 : wrapped_func_ref_(functor) {} 81 82 // Null FunctionRefs are not allowed. 83 FunctionRef() = delete; 84 85 FunctionRef(const FunctionRef&) = default; 86 // Reduce the likelihood of lifetime bugs by disallowing assignment. 87 FunctionRef& operator=(const FunctionRef&) = delete; 88 operator()89 R operator()(Args... args) const { 90 return wrapped_func_ref_(std::forward<Args>(args)...); 91 } 92 ToAbsl()93 absl::FunctionRef<R(Args...)> ToAbsl() const { return wrapped_func_ref_; } 94 95 // In Chrome, converting to `absl::FunctionRef` should be explicitly done 96 // through `ToAbsl()`. 97 template <typename Signature> 98 operator absl::FunctionRef<Signature>() = delete; 99 100 private: 101 absl::FunctionRef<R(Args...)> wrapped_func_ref_; 102 }; 103 104 } // namespace base 105 106 #endif // BASE_FUNCTIONAL_FUNCTION_REF_H_ 107