File: function_ref.h

package info (click to toggle)
chromium 120.0.6099.224-1~deb11u1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 6,112,112 kB
  • sloc: cpp: 32,907,025; ansic: 8,148,123; javascript: 3,679,536; python: 2,031,248; asm: 959,718; java: 804,675; xml: 617,256; sh: 111,417; objc: 100,835; perl: 88,443; cs: 53,032; makefile: 29,579; fortran: 24,137; php: 21,162; tcl: 21,147; sql: 20,809; ruby: 17,735; pascal: 12,864; yacc: 8,045; lisp: 3,388; lex: 1,323; ada: 727; awk: 329; jsp: 267; csh: 117; exp: 43; sed: 37
file content (106 lines) | stat: -rw-r--r-- 4,062 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef BASE_FUNCTIONAL_FUNCTION_REF_H_
#define BASE_FUNCTIONAL_FUNCTION_REF_H_

#include <type_traits>
#include <utility>

#include "base/functional/bind_internal.h"
#include "third_party/abseil-cpp/absl/base/attributes.h"
#include "third_party/abseil-cpp/absl/functional/function_ref.h"

namespace base {

template <typename Signature>
class FunctionRef;

// A non-owning reference to any invocable object (e.g. function pointer, method
// pointer, functor, lambda, et cetera) suitable for use as a type-erased
// argument to ForEach-style functions or other visitor patterns that:
//
// - do not need to copy or take ownership of the argument
// - synchronously call the invocable that was passed as an argument
//
// `base::FunctionRef` makes no heap allocations: it is trivially copyable and
// should be passed by value.
//
// `base::FunctionRef` has no null/empty state: a `base::FunctionRef` is always
// valid to invoke.
//
// The usual lifetime precautions for other non-owning references types (e.g.
// `base::StringPiece`, `base::span`) also apply to `base::FunctionRef`.
// `base::FunctionRef` should typically be used as an argument; returning a
// `base::FunctionRef` or storing a `base::FunctionRef` as a field is dangerous
// and likely to result in lifetime bugs.
//
// `base::RepeatingCallback` and `base::BindRepeating()` is another common way
// to represent type-erased invocable objects. In contrast, it requires a heap
// allocation and is not trivially copyable. It should be used when there are
// ownership requirements (e.g. partial application of arguments to a function
// stored for asynchronous execution).
//
// Note: `base::FunctionRef` is similar to `absl::FunctionRef<R(Args...)>`, but
// with stricter conversions between function types. Return type conversions are
// allowed (e.g. `int` -> `bool`, `Derived*` -> `Base*`); other than that,
// function parameter types must match exactly, and return values may not be
// silently discarded, e.g. `absl::FunctionRef` allows the following:
//
//   // Silently discards `42`.
//   [] (absl::FunctionRef<void()> r) {
//     r();
//   }([] { return 42; });
//
// But with `base::FunctionRef`:
//
//   // Does not compile!
//   [] (base::FunctionRef<void()> r) {
//     r();
//   }([] { return 42; });
template <typename R, typename... Args>
class FunctionRef<R(Args...)> {
 private:
  template <typename Functor,
            typename FunctorReturnType =
                typename internal::BindTypeHelper<Functor>::ReturnType,
            typename FunctorArgsAsTypeList =
                typename internal::BindTypeHelper<Functor>::RunParamsList>
  using EnableIfCompatible = std::enable_if_t<
      std::is_convertible_v<FunctorReturnType, R> &&
      std::is_same_v<FunctorArgsAsTypeList, internal::TypeList<Args...>>>;

 public:
  // `ABSL_ATTRIBUTE_LIFETIME_BOUND` is important since `FunctionRef` retains
  // only a reference to `functor`, `functor` must outlive `this`.
  template <typename Functor, typename = EnableIfCompatible<Functor>>
  // NOLINTNEXTLINE(google-explicit-constructor)
  FunctionRef(const Functor& functor ABSL_ATTRIBUTE_LIFETIME_BOUND)
      : wrapped_func_ref_(functor) {}

  // Null FunctionRefs are not allowed.
  FunctionRef() = delete;

  FunctionRef(const FunctionRef&) = default;
  // Reduce the likelihood of lifetime bugs by disallowing assignment.
  FunctionRef& operator=(const FunctionRef&) = delete;

  R operator()(Args... args) const {
    return wrapped_func_ref_(std::forward<Args>(args)...);
  }

  absl::FunctionRef<R(Args...)> ToAbsl() const { return wrapped_func_ref_; }

  // In Chrome, converting to `absl::FunctionRef` should be explicitly done
  // through `ToAbsl()`.
  template <typename Signature>
  operator absl::FunctionRef<Signature>() = delete;

 private:
  absl::FunctionRef<R(Args...)> wrapped_func_ref_;
};

}  // namespace base

#endif  // BASE_FUNCTIONAL_FUNCTION_REF_H_