Coverage Report

Created: 2025-10-10 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/abseil-cpp/absl/functional/function_ref.h
Line
Count
Source
1
// Copyright 2019 The Abseil Authors.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//      https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
//
15
// -----------------------------------------------------------------------------
16
// File: function_ref.h
17
// -----------------------------------------------------------------------------
18
//
19
// This header file defines the `absl::FunctionRef` type for holding a
20
// non-owning reference to an object of any invocable type. This function
21
// reference is typically most useful as a type-erased argument type for
22
// accepting function types that neither take ownership nor copy the type; using
23
// the reference type in this case avoids a copy and an allocation. Best
24
// practices of other non-owning reference-like objects (such as
25
// `absl::string_view`) apply here.
26
//
27
//  An `absl::FunctionRef` is similar in usage to a `std::function` but has the
28
//  following differences:
29
//
30
//  * It doesn't own the underlying object.
31
//  * It doesn't have a null or empty state.
32
//  * It never performs deep copies or allocations.
33
//  * It's much faster and cheaper to construct.
34
//  * It's trivially copyable and destructable.
35
//
36
// Generally, `absl::FunctionRef` should not be used as a return value, data
37
// member, or to initialize a `std::function`. Such usages will often lead to
38
// problematic lifetime issues. Once you convert something to an
39
// `absl::FunctionRef` you cannot make a deep copy later.
40
//
41
// This class is suitable for use wherever a "const std::function<>&"
42
// would be used without making a copy. ForEach functions and other versions of
43
// the visitor pattern are a good example of when this class should be used.
44
//
45
// This class is trivial to copy and should be passed by value.
46
#ifndef ABSL_FUNCTIONAL_FUNCTION_REF_H_
47
#define ABSL_FUNCTIONAL_FUNCTION_REF_H_
48
49
#include <cassert>
50
#include <type_traits>
51
#include <utility>
52
53
#include "absl/base/attributes.h"
54
#include "absl/base/config.h"
55
#include "absl/functional/internal/function_ref.h"
56
#include "absl/meta/type_traits.h"
57
#include "absl/utility/utility.h"
58
59
namespace absl {
60
ABSL_NAMESPACE_BEGIN
61
62
// FunctionRef
63
//
64
// Dummy class declaration to allow the partial specialization based on function
65
// types below.
66
template <typename T>
67
class FunctionRef;
68
69
// FunctionRef
70
//
71
// An `absl::FunctionRef` is a lightweight wrapper to any invocable object with
72
// a compatible signature. Generally, an `absl::FunctionRef` should only be used
73
// as an argument type and should be preferred as an argument over a const
74
// reference to a `std::function`. `absl::FunctionRef` itself does not allocate,
75
// although the wrapped invocable may.
76
//
77
// Example:
78
//
79
//   // The following function takes a function callback by const reference
80
//   bool Visitor(const std::function<void(my_proto&,
81
//                                         absl::string_view)>& callback);
82
//
83
//   // Assuming that the function is not stored or otherwise copied, it can be
84
//   // replaced by an `absl::FunctionRef`:
85
//   bool Visitor(absl::FunctionRef<void(my_proto&, absl::string_view)>
86
//                  callback);
87
template <typename R, typename... Args>
88
class ABSL_ATTRIBUTE_VIEW FunctionRef<R(Args...)> {
89
 protected:
90
  // Used to disable constructors for objects that are not compatible with the
91
  // signature of this FunctionRef.
92
  template <typename F, typename... U>
93
  using EnableIfCompatible =
94
      std::enable_if_t<std::is_invocable_r<R, F, U..., Args...>::value>;
95
96
  // Internal constructor to supersede the copying constructor
97
  template <typename F>
98
  // NOLINTNEXTLINE(google-explicit-constructor)
99
  FunctionRef(std::in_place_t, F&& f ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept
100
27.9k
      : invoker_(&absl::functional_internal::InvokeObject<F&, R, Args...>) {
101
27.9k
    absl::functional_internal::AssertNonNull(f);
102
27.9k
    ptr_.obj = &f;
103
27.9k
  }
absl::FunctionRef<unsigned long (unsigned long)>::FunctionRef<absl::container_internal::HashKey<absl::container_internal::StringHash, std::__1::basic_string_view<char, std::__1::char_traits<char> >, true> >(std::__1::in_place_t, absl::container_internal::HashKey<absl::container_internal::StringHash, std::__1::basic_string_view<char, std::__1::char_traits<char> >, true>&&)
Line
Count
Source
100
4
      : invoker_(&absl::functional_internal::InvokeObject<F&, R, Args...>) {
101
4
    absl::functional_internal::AssertNonNull(f);
102
4
    ptr_.obj = &f;
103
4
  }
float_conversion.cc:absl::FunctionRef<void (absl::Span<unsigned int>)>::FunctionRef<absl::str_format_internal::(anonymous namespace)::BinaryToDecimal::RunConversion(absl::uint128, int, absl::FunctionRef<void (absl::str_format_internal::(anonymous namespace)::BinaryToDecimal)>)::{lambda(absl::Span<unsigned int>)#1}>(std::__1::in_place_t, absl::str_format_internal::(anonymous namespace)::BinaryToDecimal::RunConversion(absl::uint128, int, absl::FunctionRef<void (absl::str_format_internal::(anonymous namespace)::BinaryToDecimal)>)::{lambda(absl::Span<unsigned int>)#1}&&)
Line
Count
Source
100
7.39k
      : invoker_(&absl::functional_internal::InvokeObject<F&, R, Args...>) {
101
7.39k
    absl::functional_internal::AssertNonNull(f);
102
7.39k
    ptr_.obj = &f;
103
7.39k
  }
float_conversion.cc:absl::FunctionRef<void (absl::str_format_internal::(anonymous namespace)::BinaryToDecimal)>::FunctionRef<absl::str_format_internal::(anonymous namespace)::FormatFPositiveExpSlow(absl::uint128, int, absl::str_format_internal::(anonymous namespace)::FormatState const&)::$_0>(std::__1::in_place_t, absl::str_format_internal::(anonymous namespace)::FormatFPositiveExpSlow(absl::uint128, int, absl::str_format_internal::(anonymous namespace)::FormatState const&)::$_0&&)
Line
Count
Source
100
7.39k
      : invoker_(&absl::functional_internal::InvokeObject<F&, R, Args...>) {
101
7.39k
    absl::functional_internal::AssertNonNull(f);
102
7.39k
    ptr_.obj = &f;
103
7.39k
  }
float_conversion.cc:absl::FunctionRef<void (absl::Span<unsigned int>)>::FunctionRef<absl::str_format_internal::(anonymous namespace)::FractionalDigitGenerator::RunConversion(absl::uint128, int, absl::FunctionRef<void (absl::str_format_internal::(anonymous namespace)::FractionalDigitGenerator)>)::{lambda(absl::Span<unsigned int>)#1}>(std::__1::in_place_t, absl::str_format_internal::(anonymous namespace)::FractionalDigitGenerator::RunConversion(absl::uint128, int, absl::FunctionRef<void (absl::str_format_internal::(anonymous namespace)::FractionalDigitGenerator)>)::{lambda(absl::Span<unsigned int>)#1}&&)
Line
Count
Source
100
6.58k
      : invoker_(&absl::functional_internal::InvokeObject<F&, R, Args...>) {
101
6.58k
    absl::functional_internal::AssertNonNull(f);
102
6.58k
    ptr_.obj = &f;
103
6.58k
  }
float_conversion.cc:absl::FunctionRef<void (absl::str_format_internal::(anonymous namespace)::FractionalDigitGenerator)>::FunctionRef<absl::str_format_internal::(anonymous namespace)::FormatFNegativeExpSlow(absl::uint128, int, absl::str_format_internal::(anonymous namespace)::FormatState const&)::$_0>(std::__1::in_place_t, absl::str_format_internal::(anonymous namespace)::FormatFNegativeExpSlow(absl::uint128, int, absl::str_format_internal::(anonymous namespace)::FormatState const&)::$_0&&)
Line
Count
Source
100
6.58k
      : invoker_(&absl::functional_internal::InvokeObject<F&, R, Args...>) {
101
6.58k
    absl::functional_internal::AssertNonNull(f);
102
6.58k
    ptr_.obj = &f;
103
6.58k
  }
104
105
 public:
106
  // Constructs a FunctionRef from any invocable type.
107
  template <typename F,
108
            typename = EnableIfCompatible<std::enable_if_t<
109
                !std::is_same_v<FunctionRef, absl::remove_cvref_t<F>>, F&>>>
110
  // NOLINTNEXTLINE(google-explicit-constructor)
111
  FunctionRef(F&& f ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept
112
27.9k
      : FunctionRef(std::in_place, std::forward<F>(f)) {}
absl::FunctionRef<unsigned long (unsigned long)>::FunctionRef<absl::container_internal::HashKey<absl::container_internal::StringHash, std::__1::basic_string_view<char, std::__1::char_traits<char> >, true>, void>(absl::container_internal::HashKey<absl::container_internal::StringHash, std::__1::basic_string_view<char, std::__1::char_traits<char> >, true>&&)
Line
Count
Source
112
4
      : FunctionRef(std::in_place, std::forward<F>(f)) {}
float_conversion.cc:absl::FunctionRef<void (absl::Span<unsigned int>)>::FunctionRef<absl::str_format_internal::(anonymous namespace)::BinaryToDecimal::RunConversion(absl::uint128, int, absl::FunctionRef<void (absl::str_format_internal::(anonymous namespace)::BinaryToDecimal)>)::{lambda(absl::Span<unsigned int>)#1}, void>(absl::str_format_internal::(anonymous namespace)::BinaryToDecimal::RunConversion(absl::uint128, int, absl::FunctionRef<void (absl::str_format_internal::(anonymous namespace)::BinaryToDecimal)>)::{lambda(absl::Span<unsigned int>)#1}&&)
Line
Count
Source
112
7.39k
      : FunctionRef(std::in_place, std::forward<F>(f)) {}
float_conversion.cc:absl::FunctionRef<void (absl::str_format_internal::(anonymous namespace)::BinaryToDecimal)>::FunctionRef<absl::str_format_internal::(anonymous namespace)::FormatFPositiveExpSlow(absl::uint128, int, absl::str_format_internal::(anonymous namespace)::FormatState const&)::$_0, void>(absl::str_format_internal::(anonymous namespace)::FormatFPositiveExpSlow(absl::uint128, int, absl::str_format_internal::(anonymous namespace)::FormatState const&)::$_0&&)
Line
Count
Source
112
7.39k
      : FunctionRef(std::in_place, std::forward<F>(f)) {}
float_conversion.cc:absl::FunctionRef<void (absl::Span<unsigned int>)>::FunctionRef<absl::str_format_internal::(anonymous namespace)::FractionalDigitGenerator::RunConversion(absl::uint128, int, absl::FunctionRef<void (absl::str_format_internal::(anonymous namespace)::FractionalDigitGenerator)>)::{lambda(absl::Span<unsigned int>)#1}, void>(absl::str_format_internal::(anonymous namespace)::FractionalDigitGenerator::RunConversion(absl::uint128, int, absl::FunctionRef<void (absl::str_format_internal::(anonymous namespace)::FractionalDigitGenerator)>)::{lambda(absl::Span<unsigned int>)#1}&&)
Line
Count
Source
112
6.58k
      : FunctionRef(std::in_place, std::forward<F>(f)) {}
float_conversion.cc:absl::FunctionRef<void (absl::str_format_internal::(anonymous namespace)::FractionalDigitGenerator)>::FunctionRef<absl::str_format_internal::(anonymous namespace)::FormatFNegativeExpSlow(absl::uint128, int, absl::str_format_internal::(anonymous namespace)::FormatState const&)::$_0, void>(absl::str_format_internal::(anonymous namespace)::FormatFNegativeExpSlow(absl::uint128, int, absl::str_format_internal::(anonymous namespace)::FormatState const&)::$_0&&)
Line
Count
Source
112
6.58k
      : FunctionRef(std::in_place, std::forward<F>(f)) {}
113
114
  // Overload for function pointers. This eliminates a level of indirection that
115
  // would happen if the above overload was used (it lets us store the pointer
116
  // instead of a pointer to a pointer).
117
  //
118
  // This overload is also used for references to functions, since references to
119
  // functions can decay to function pointers implicitly.
120
  template <typename F, typename = EnableIfCompatible<F*>,
121
            absl::functional_internal::EnableIf<std::is_function_v<F>> = 0>
122
  // NOLINTNEXTLINE(google-explicit-constructor)
123
  FunctionRef(F* f ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept
124
      : invoker_(&absl::functional_internal::InvokeFunction<F*, R, Args...>) {
125
    assert(f != nullptr);
126
    ptr_.fun = reinterpret_cast<decltype(ptr_.fun)>(f);
127
  }
128
129
#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
130
  // Similar to the other overloads, but passes the address of a known callable
131
  // `F` at compile time. This allows calling arbitrary functions while avoiding
132
  // an indirection.
133
  // Needs C++20 as `nontype_t` needs C++20 for `auto` template parameters.
134
  template <auto F, typename = EnableIfCompatible<decltype(F)>>
135
  FunctionRef(nontype_t<F>) noexcept  // NOLINT(google-explicit-constructor)
136
      : invoker_(&absl::functional_internal::InvokeFunction<decltype(F), F, R,
137
                                                            Args...>) {}
138
139
  template <
140
      auto F, typename Obj,
141
      typename = EnableIfCompatible<decltype(F), std::remove_reference_t<Obj>&>,
142
      absl::functional_internal::EnableIf<!std::is_rvalue_reference_v<Obj&&>> =
143
          0>
144
  // NOLINTNEXTLINE(google-explicit-constructor)
145
  FunctionRef(nontype_t<F>, Obj&& obj ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept
146
      : invoker_(&absl::functional_internal::InvokeObject<Obj&, decltype(F), F,
147
                                                          R, Args...>) {
148
    ptr_.obj = std::addressof(obj);
149
  }
150
151
  template <auto F, typename Obj,
152
            typename = EnableIfCompatible<decltype(F), Obj*>>
153
  // NOLINTNEXTLINE(google-explicit-constructor)
154
  FunctionRef(nontype_t<F>, Obj* obj ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept
155
      : invoker_(&absl::functional_internal::InvokePtr<Obj, decltype(F), F, R,
156
                                                       Args...>) {
157
    ptr_.obj = obj;
158
  }
159
#endif
160
161
  using absl_internal_is_view = std::true_type;
162
163
  // Call the underlying object.
164
27.9k
  R operator()(Args... args) const {
165
27.9k
    return invoker_(ptr_, std::forward<Args>(args)...);
166
27.9k
  }
Unexecuted instantiation: absl::FunctionRef<void (std::__1::basic_string_view<char, std::__1::char_traits<char> >)>::operator()(std::__1::basic_string_view<char, std::__1::char_traits<char> >) const
Unexecuted instantiation: absl::FunctionRef<void (absl::container_internal::ctrl_t const*, void*)>::operator()(absl::container_internal::ctrl_t const*, void*) const
absl::FunctionRef<unsigned long (unsigned long)>::operator()(unsigned long) const
Line
Count
Source
164
2
  R operator()(Args... args) const {
165
2
    return invoker_(ptr_, std::forward<Args>(args)...);
166
2
  }
Unexecuted instantiation: absl::FunctionRef<void (void*, void const*)>::operator()(void*, void const*) const
absl::FunctionRef<void (absl::Span<unsigned int>)>::operator()(absl::Span<unsigned int>) const
Line
Count
Source
164
13.9k
  R operator()(Args... args) const {
165
13.9k
    return invoker_(ptr_, std::forward<Args>(args)...);
166
13.9k
  }
float_conversion.cc:absl::FunctionRef<void (absl::str_format_internal::(anonymous namespace)::BinaryToDecimal)>::operator()(absl::str_format_internal::(anonymous namespace)::BinaryToDecimal) const
Line
Count
Source
164
7.39k
  R operator()(Args... args) const {
165
7.39k
    return invoker_(ptr_, std::forward<Args>(args)...);
166
7.39k
  }
float_conversion.cc:absl::FunctionRef<void (absl::str_format_internal::(anonymous namespace)::FractionalDigitGenerator)>::operator()(absl::str_format_internal::(anonymous namespace)::FractionalDigitGenerator) const
Line
Count
Source
164
6.58k
  R operator()(Args... args) const {
165
6.58k
    return invoker_(ptr_, std::forward<Args>(args)...);
166
6.58k
  }
167
168
 private:
169
  absl::functional_internal::VoidPtr ptr_;
170
  absl::functional_internal::Invoker<R, Args...> invoker_;
171
};
172
173
// Allow const qualified function signatures. Since FunctionRef requires
174
// constness anyway we can just make this a no-op.
175
template <typename R, typename... Args>
176
class ABSL_ATTRIBUTE_VIEW
177
    FunctionRef<R(Args...) const> : private FunctionRef<R(Args...)> {
178
  using Base = FunctionRef<R(Args...)>;
179
180
  template <typename F, typename... U>
181
  using EnableIfCompatible =
182
      typename Base::template EnableIfCompatible<F, U...>;
183
184
 public:
185
  template <
186
      typename F,
187
      typename = EnableIfCompatible<std::enable_if_t<
188
          !std::is_same_v<FunctionRef, absl::remove_cvref_t<F>>, const F&>>>
189
  // NOLINTNEXTLINE(google-explicit-constructor)
190
  FunctionRef(const F& f ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept
191
      : Base(std::in_place_t(), f) {}
192
193
  template <typename F, typename = EnableIfCompatible<F*>,
194
            absl::functional_internal::EnableIf<std::is_function_v<F>> = 0>
195
  // NOLINTNEXTLINE(google-explicit-constructor)
196
  FunctionRef(F* f ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept : Base(f) {}
197
198
#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
199
  template <auto F, typename = EnableIfCompatible<decltype(F)>>
200
  // NOLINTNEXTLINE(google-explicit-constructor)
201
  FunctionRef(nontype_t<F> arg) noexcept : Base(arg) {}
202
203
  template <auto F, typename Obj,
204
            typename = EnableIfCompatible<decltype(F),
205
                                          const std::remove_reference_t<Obj>&>,
206
            absl::functional_internal::EnableIf<
207
                !std::is_rvalue_reference_v<Obj&&>> = 0>
208
  // NOLINTNEXTLINE(google-explicit-constructor)
209
  FunctionRef(nontype_t<F> arg,
210
              Obj&& obj ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept
211
      : Base(arg, std::forward<Obj>(obj)) {}
212
213
  template <auto F, typename Obj,
214
            typename = EnableIfCompatible<decltype(F), const Obj*>>
215
  // NOLINTNEXTLINE(google-explicit-constructor)
216
  FunctionRef(nontype_t<F> arg,
217
              const Obj* obj ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept
218
      : Base(arg, obj) {}
219
#endif
220
221
  using absl_internal_is_view = std::true_type;
222
223
  using Base::operator();
224
};
225
226
template <class F>
227
FunctionRef(F*) -> FunctionRef<F>;
228
229
#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
230
template <auto Func>
231
FunctionRef(nontype_t<Func>)
232
    -> FunctionRef<std::remove_pointer_t<decltype(Func)>>;
233
234
template <class M, class T, M T::* Func, class U>
235
FunctionRef(nontype_t<Func>, U&&)
236
    -> FunctionRef<std::enable_if_t<std::is_member_pointer_v<M T::*>, M>>;
237
238
template <class M, class T, M T::* Func, class U>
239
FunctionRef(nontype_t<Func>, U&&) -> FunctionRef<std::enable_if_t<
240
    std::is_object_v<M>, std::invoke_result_t<decltype(Func), U&>()>>;
241
242
template <class R, class T, class... Args, R (*Func)(T, Args...), class U>
243
FunctionRef(nontype_t<Func>, U&&) -> FunctionRef<R(Args...)>;
244
#endif
245
246
ABSL_NAMESPACE_END
247
}  // namespace absl
248
249
#endif  // ABSL_FUNCTIONAL_FUNCTION_REF_H_