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 <concepts> 9 #include <type_traits> 10 #include <utility> 11 12 #include "base/functional/bind_internal.h" 13 #include "base/types/is_instantiation.h" 14 #include "third_party/abseil-cpp/absl/base/attributes.h" 15 #include "third_party/abseil-cpp/absl/functional/function_ref.h" 16 17 namespace base { 18 19 template <typename Signature> 20 class FunctionRef; 21 22 // A non-owning reference to any invocable object (e.g. function pointer, method 23 // pointer, functor, lambda, et cetera) suitable for use as a type-erased 24 // argument to ForEach-style functions or other visitor patterns that: 25 // 26 // - do not need to copy or take ownership of the argument 27 // - synchronously call the invocable that was passed as an argument 28 // 29 // `base::FunctionRef` makes no heap allocations: it is trivially copyable and 30 // should be passed by value. 31 // 32 // `base::FunctionRef` has no null/empty state: a `base::FunctionRef` is always 33 // valid to invoke. 34 // 35 // The usual lifetime precautions for other non-owning references types (e.g. 36 // `base::StringPiece`, `base::span`) also apply to `base::FunctionRef`. 37 // `base::FunctionRef` should typically be used as an argument; returning a 38 // `base::FunctionRef` or storing a `base::FunctionRef` as a field is dangerous 39 // and likely to result in lifetime bugs. 40 // 41 // `base::RepeatingCallback` and `base::BindRepeating()` is another common way 42 // to represent type-erased invocable objects. In contrast, it requires a heap 43 // allocation and is not trivially copyable. It should be used when there are 44 // ownership requirements (e.g. partial application of arguments to a function 45 // stored for asynchronous execution). 46 // 47 // Note: `base::FunctionRef` is similar to `absl::FunctionRef<R(Args...)>`, but 48 // with stricter conversions between function types. Return type conversions are 49 // allowed (e.g. `int` -> `bool`, `Derived*` -> `Base*`); other than that, 50 // function parameter types must match exactly, and return values may not be 51 // silently discarded, e.g. `absl::FunctionRef` allows the following: 52 // 53 // // Silently discards `42`. 54 // [] (absl::FunctionRef<void()> r) { 55 // r(); 56 // }([] { return 42; }); 57 // 58 // But with `base::FunctionRef`: 59 // 60 // // Does not compile! 61 // [] (base::FunctionRef<void()> r) { 62 // r(); 63 // }([] { return 42; }); 64 template <typename R, typename... Args> 65 class FunctionRef<R(Args...)> { 66 template <typename Functor, 67 typename RunType = internal::FunctorTraits<Functor>::RunType> 68 static constexpr bool kCompatibleFunctor = 69 std::convertible_to<internal::ExtractReturnType<RunType>, R> && 70 std::same_as<internal::ExtractArgs<RunType>, internal::TypeList<Args...>>; 71 72 public: 73 // `ABSL_ATTRIBUTE_LIFETIME_BOUND` is important; since `FunctionRef` retains 74 // only a reference to `functor`, `functor` must outlive `this`. 75 template <typename Functor> 76 requires kCompatibleFunctor<Functor> && 77 // Prevent this constructor from participating in overload 78 // resolution if the callable is itself an instantiation of the 79 // `FunctionRef` template. 80 // 81 // If the callable is a `FunctionRef` with exactly the same 82 // signature as us, then the copy constructor will be used instead, 83 // so this has no effect. (Note that if the constructor argument 84 // were `Functor&&`, this exclusion would be necessary to force the 85 // choice of the copy constructor over this one for non-const ref 86 // args; see https://stackoverflow.com/q/57909923.) 87 // 88 // If the callable is a `FunctionRef` with some other signature 89 // then we choose not to support binding to it at all. Conceivably 90 // we could teach our trampoline to deal with this, but this may be 91 // the sign of an object lifetime bug, and again it's not clear 92 // that this isn't just a mistake on the part of the user. 93 (!internal::is_instantiation_v<FunctionRef, 94 std::decay_t<Functor>>) && 95 // For the same reason as the second case above, prevent 96 // construction from `absl::FunctionRef`. 97 (!internal::is_instantiation_v<absl::FunctionRef, 98 std::decay_t<Functor>>) 99 // NOLINTNEXTLINE(google-explicit-constructor) FunctionRef(const Functor & functor ABSL_ATTRIBUTE_LIFETIME_BOUND)100 FunctionRef(const Functor& functor ABSL_ATTRIBUTE_LIFETIME_BOUND) 101 : wrapped_func_ref_(functor) {} 102 103 // Constructs a reference to the given function pointer. This constructor 104 // serves to exclude this case from lifetime analysis, since the underlying 105 // code pointed to by a function pointer is safe to invoke even if the 106 // lifetime of the pointer provided doesn't outlive us, e.g.: 107 // `const FunctionRef<void(int)> ref = +[](int i) { ... };` 108 // Without this constructor, the above code would warn about dangling refs. 109 // TODO(pkasting): Also support ptr-to-member-functions; this requires changes 110 // in `absl::FunctionRef` or else rewriting this class to not use that one. 111 template <typename Func> 112 requires kCompatibleFunctor<Func*> 113 // NOLINTNEXTLINE(google-explicit-constructor) FunctionRef(Func * func)114 FunctionRef(Func* func) : wrapped_func_ref_(func) {} 115 116 // Null FunctionRefs are not allowed. 117 FunctionRef() = delete; 118 119 FunctionRef(const FunctionRef&) = default; 120 // Reduce the likelihood of lifetime bugs by disallowing assignment. 121 FunctionRef& operator=(const FunctionRef&) = delete; 122 operator()123 R operator()(Args... args) const { 124 return wrapped_func_ref_(std::forward<Args>(args)...); 125 } 126 127 private: 128 absl::FunctionRef<R(Args...)> wrapped_func_ref_; 129 }; 130 131 } // namespace base 132 133 #endif // BASE_FUNCTIONAL_FUNCTION_REF_H_ 134