internal/any_invocable.h
Go to the documentation of this file.
1 // Copyright 2022 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 // Implementation details for `absl::AnyInvocable`
16 
17 #ifndef ABSL_FUNCTIONAL_INTERNAL_ANY_INVOCABLE_H_
18 #define ABSL_FUNCTIONAL_INTERNAL_ANY_INVOCABLE_H_
19 
21 // //
22 // This implementation of the proposed `any_invocable` uses an approach that //
23 // chooses between local storage and remote storage for the contained target //
24 // object based on the target object's size, alignment requirements, and //
25 // whether or not it has a nothrow move constructor. Additional optimizations //
26 // are performed when the object is a trivially copyable type [basic.types]. //
27 // //
28 // There are three datamembers per `AnyInvocable` instance //
29 // //
30 // 1) A union containing either //
31 // - A pointer to the target object referred to via a void*, or //
32 // - the target object, emplaced into a raw char buffer //
33 // //
34 // 2) A function pointer to a "manager" function operation that takes a //
35 // discriminator and logically branches to either perform a move operation //
36 // or destroy operation based on that discriminator. //
37 // //
38 // 3) A function pointer to an "invoker" function operation that invokes the //
39 // target object, directly returning the result. //
40 // //
41 // When in the logically empty state, the manager function is an empty //
42 // function and the invoker function is one that would be undefined-behavior //
43 // to call. //
44 // //
45 // An additional optimization is performed when converting from one //
46 // AnyInvocable to another where only the noexcept specification and/or the //
47 // cv/ref qualifiers of the function type differ. In these cases, the //
48 // conversion works by "moving the guts", similar to if they were the same //
49 // exact type, as opposed to having to perform an additional layer of //
50 // wrapping through remote storage. //
51 // //
53 
54 // IWYU pragma: private, include "absl/functional/any_invocable.h"
55 
56 #include <cassert>
57 #include <cstddef>
58 #include <cstring>
59 #include <functional>
60 #include <initializer_list>
61 #include <memory>
62 #include <new>
63 #include <type_traits>
64 #include <utility>
65 
66 #include "absl/base/config.h"
67 #include "absl/base/internal/invoke.h"
68 #include "absl/base/macros.h"
69 #include "absl/meta/type_traits.h"
70 #include "absl/utility/utility.h"
71 
72 namespace absl {
74 
75 // Helper macro used to prevent spelling `noexcept` in language versions older
76 // than C++17, where it is not part of the type system, in order to avoid
77 // compilation failures and internal compiler errors.
78 #if ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
79 #define ABSL_INTERNAL_NOEXCEPT_SPEC(noex) noexcept(noex)
80 #else
81 #define ABSL_INTERNAL_NOEXCEPT_SPEC(noex)
82 #endif
83 
84 // Defined in functional/any_invocable.h
85 template <class Sig>
86 class AnyInvocable;
87 
88 namespace internal_any_invocable {
89 
90 // Constants relating to the small-object-storage for AnyInvocable
91 enum StorageProperty : std::size_t {
92  kAlignment = alignof(std::max_align_t), // The alignment of the storage
93  kStorageSize = sizeof(void*) * 2 // The size of the storage
94 };
95 
97 //
98 // A metafunction for checking if a type is an AnyInvocable instantiation.
99 // This is used during conversion operations.
100 template <class T>
102 
103 template <class Sig>
105 //
107 
108 // A type trait that tells us whether or not a target function type should be
109 // stored locally in the small object optimization storage
110 template <class T>
111 using IsStoredLocally = std::integral_constant<
112  bool, sizeof(T) <= kStorageSize && alignof(T) <= kAlignment &&
113  kAlignment % alignof(T) == 0 &&
115 
116 // An implementation of std::remove_cvref_t of C++20.
117 template <class T>
118 using RemoveCVRef =
120 
122 //
123 // An implementation of the C++ standard INVOKE<R> pseudo-macro, operation is
124 // equivalent to std::invoke except that it forces an implicit conversion to the
125 // specified return type. If "R" is void, the function is executed and the
126 // return value is simply ignored.
127 template <class ReturnType, class F, class... P,
129 void InvokeR(F&& f, P&&... args) {
130  absl::base_internal::invoke(std::forward<F>(f), std::forward<P>(args)...);
131 }
132 
133 template <class ReturnType, class F, class... P,
135 ReturnType InvokeR(F&& f, P&&... args) {
136  return absl::base_internal::invoke(std::forward<F>(f),
137  std::forward<P>(args)...);
138 }
139 
140 //
142 
145 // A metafunction that takes a "T" corresponding to a parameter type of the
146 // user's specified function type, and yields the parameter type to use for the
147 // type-erased invoker. In order to prevent observable moves, this must be
148 // either a reference or, if the type is trivial, the original parameter type
149 // itself. Since the parameter type may be incomplete at the point that this
150 // metafunction is used, we can only do this optimization for scalar types
151 // rather than for any trivial type.
152 template <typename T>
154 
155 template <typename T>
157 
158 // NOTE: We deliberately use an intermediate struct instead of a direct alias,
159 // as a workaround for b/206991861 on MSVC versions < 1924.
160 template <class T>
162  using type = decltype((
163  ForwardImpl<T>)(std::integral_constant<bool,
165 };
166 
167 template <class T>
169 //
171 
172 // A discriminator when calling the "manager" function that describes operation
173 // type-erased operation should be invoked.
174 //
175 // "relocate_from_to" specifies that the manager should perform a move.
176 //
177 // "dispose" specifies that the manager should perform a destroy.
179 
180 // The portion of `AnyInvocable` state that contains either a pointer to the
181 // target object or the object itself in local storage
183  struct {
184  // A pointer to the type-erased object when remotely stored
185  void* target;
186  // The size of the object for `RemoteManagerTrivial`
187  std::size_t size;
188  } remote;
189 
190  // Local-storage for the type-erased object when small and trivial enough
192 };
193 
194 // A typed accessor for the object in `TypeErasedState` storage
195 template <class T>
197  // We launder here because the storage may be reused with the same type.
198 #if ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
199  return *std::launder(reinterpret_cast<T*>(&state->storage));
200 #elif ABSL_HAVE_BUILTIN(__builtin_launder)
201  return *__builtin_launder(reinterpret_cast<T*>(&state->storage));
202 #else
203 
204  // When `std::launder` or equivalent are not available, we rely on undefined
205  // behavior, which works as intended on Abseil's officially supported
206  // platforms as of Q2 2022.
207 #if !defined(__clang__) && defined(__GNUC__)
208 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
209 #pragma GCC diagnostic push
210 #endif
211  return *reinterpret_cast<T*>(&state->storage);
212 #if !defined(__clang__) && defined(__GNUC__)
213 #pragma GCC diagnostic pop
214 #endif
215 
216 #endif
217 }
218 
219 // The type for functions issuing lifetime-related operations: move and dispose
220 // A pointer to such a function is contained in each `AnyInvocable` instance.
221 // NOTE: When specifying `FunctionToCall::`dispose, the same state must be
222 // passed as both "from" and "to".
223 using ManagerType = void(FunctionToCall /*operation*/,
224  TypeErasedState* /*from*/, TypeErasedState* /*to*/)
226 
227 // The type for functions issuing the actual invocation of the object
228 // A pointer to such a function is contained in each AnyInvocable instance.
229 template <bool SigIsNoexcept, class ReturnType, class... P>
230 using InvokerType = ReturnType(TypeErasedState*, ForwardedParameterType<P>...)
232 
233 // The manager that is used when AnyInvocable is empty
234 inline void EmptyManager(FunctionToCall /*operation*/,
235  TypeErasedState* /*from*/,
236  TypeErasedState* /*to*/) noexcept {}
237 
238 // The manager that is used when a target function is in local storage and is
239 // a trivially copyable type.
240 inline void LocalManagerTrivial(FunctionToCall /*operation*/,
241  TypeErasedState* const from,
242  TypeErasedState* const to) noexcept {
243  // This single statement without branching handles both possible operations.
244  //
245  // For FunctionToCall::dispose, "from" and "to" point to the same state, and
246  // so this assignment logically would do nothing.
247  //
248  // Note: Correctness here relies on http://wg21.link/p0593, which has only
249  // become standard in C++20, though implementations do not break it in
250  // practice for earlier versions of C++.
251  //
252  // The correct way to do this without that paper is to first placement-new a
253  // default-constructed T in "to->storage" prior to the memmove, but doing so
254  // requires a different function to be created for each T that is stored
255  // locally, which can cause unnecessary bloat and be less cache friendly.
256  *to = *from;
257 
258  // Note: Because the type is trivially copyable, the destructor does not need
259  // to be called ("trivially copyable" requires a trivial destructor).
260 }
261 
262 // The manager that is used when a target function is in local storage and is
263 // not a trivially copyable type.
264 template <class T>
266  TypeErasedState* const from,
267  TypeErasedState* const to) noexcept {
268  static_assert(IsStoredLocally<T>::value,
269  "Local storage must only be used for supported types.");
271  "Locally stored types must be trivially copyable.");
272 
273  T& from_object = (ObjectInLocalStorage<T>)(from);
274 
275  switch (operation) {
277  // NOTE: Requires that the left-hand operand is already empty.
278  ::new (static_cast<void*>(&to->storage)) T(std::move(from_object));
281  from_object.~T(); // Must not throw. // NOLINT
282  return;
283  }
285 }
286 
287 // The invoker that is used when a target function is in local storage
288 // Note: QualTRef here is the target function type along with cv and reference
289 // qualifiers that must be used when calling the function.
290 template <bool SigIsNoexcept, class ReturnType, class QualTRef, class... P>
291 ReturnType LocalInvoker(
292  TypeErasedState* const state,
293  ForwardedParameterType<P>... args) noexcept(SigIsNoexcept) {
294  using RawT = RemoveCVRef<QualTRef>;
295  static_assert(
297  "Target object must be in local storage in order to be invoked from it.");
298 
299  auto& f = (ObjectInLocalStorage<RawT>)(state);
300  return (InvokeR<ReturnType>)(static_cast<QualTRef>(f),
301  static_cast<ForwardedParameterType<P>>(args)...);
302 }
303 
304 // The manager that is used when a target function is in remote storage and it
305 // has a trivial destructor
306 inline void RemoteManagerTrivial(FunctionToCall operation,
307  TypeErasedState* const from,
308  TypeErasedState* const to) noexcept {
309  switch (operation) {
311  // NOTE: Requires that the left-hand operand is already empty.
312  to->remote = from->remote;
313  return;
315 #if defined(__cpp_sized_deallocation)
316  ::operator delete(from->remote.target, from->remote.size);
317 #else // __cpp_sized_deallocation
318  ::operator delete(from->remote.target);
319 #endif // __cpp_sized_deallocation
320  return;
321  }
323 }
324 
325 // The manager that is used when a target function is in remote storage and the
326 // destructor of the type is not trivial
327 template <class T>
329  TypeErasedState* const from,
330  TypeErasedState* const to) noexcept {
331  static_assert(!IsStoredLocally<T>::value,
332  "Remote storage must only be used for types that do not "
333  "qualify for local storage.");
334 
335  switch (operation) {
337  // NOTE: Requires that the left-hand operand is already empty.
338  to->remote.target = from->remote.target;
339  return;
341  ::delete static_cast<T*>(from->remote.target); // Must not throw.
342  return;
343  }
345 }
346 
347 // The invoker that is used when a target function is in remote storage
348 template <bool SigIsNoexcept, class ReturnType, class QualTRef, class... P>
349 ReturnType RemoteInvoker(
350  TypeErasedState* const state,
351  ForwardedParameterType<P>... args) noexcept(SigIsNoexcept) {
352  using RawT = RemoveCVRef<QualTRef>;
353  static_assert(!IsStoredLocally<RawT>::value,
354  "Target object must be in remote storage in order to be "
355  "invoked from it.");
356 
357  auto& f = *static_cast<RawT*>(state->remote.target);
358  return (InvokeR<ReturnType>)(static_cast<QualTRef>(f),
359  static_cast<ForwardedParameterType<P>>(args)...);
360 }
361 
363 //
364 // A metafunction that checks if a type T is an instantiation of
365 // absl::in_place_type_t (needed for constructor constraints of AnyInvocable).
366 template <class T>
368 
369 template <class T>
371 //
373 
374 // A constructor name-tag used with CoreImpl (below) to request the
375 // conversion-constructor. QualDecayedTRef is the decayed-type of the object to
376 // wrap, along with the cv and reference qualifiers that must be applied when
377 // performing an invocation of the wrapped object.
378 template <class QualDecayedTRef>
380 
381 // A helper base class for all core operations of AnyInvocable. Most notably,
382 // this class creates the function call operator and constraint-checkers so that
383 // the top-level class does not have to be a series of partial specializations.
384 //
385 // Note: This definition exists (as opposed to being a declaration) so that if
386 // the user of the top-level template accidentally passes a template argument
387 // that is not a function type, they will get a static_assert in AnyInvocable's
388 // class body rather than an error stating that Impl is not defined.
389 template <class Sig>
390 class Impl {}; // Note: This is partially-specialized later.
391 
392 // A std::unique_ptr deleter that deletes memory allocated via ::operator new.
393 #if defined(__cpp_sized_deallocation)
394 class TrivialDeleter {
395  public:
396  explicit TrivialDeleter(std::size_t size) : size_(size) {}
397 
398  void operator()(void* target) const {
399  ::operator delete(target, size_);
400  }
401 
402  private:
403  std::size_t size_;
404 };
405 #else // __cpp_sized_deallocation
407  public:
408  explicit TrivialDeleter(std::size_t) {}
409 
410  void operator()(void* target) const { ::operator delete(target); }
411 };
412 #endif // __cpp_sized_deallocation
413 
414 template <bool SigIsNoexcept, class ReturnType, class... P>
415 class CoreImpl;
416 
417 constexpr bool IsCompatibleConversion(void*, void*) { return false; }
418 template <bool NoExceptSrc, bool NoExceptDest, class... T>
421  return !NoExceptDest || NoExceptSrc;
422 }
423 
424 // A helper base class for all core operations of AnyInvocable that do not
425 // depend on the cv/ref qualifiers of the function type.
426 template <bool SigIsNoexcept, class ReturnType, class... P>
427 class CoreImpl {
428  public:
429  using result_type = ReturnType;
430 
431  CoreImpl() noexcept : manager_(EmptyManager), invoker_(nullptr) {}
432 
433  enum class TargetType : int {
434  kPointer = 0,
437  kOther = 3,
438  };
439 
440  // Note: QualDecayedTRef here includes the cv-ref qualifiers associated with
441  // the invocation of the Invocable. The unqualified type is the target object
442  // type to be stored.
443  template <class QualDecayedTRef, class F>
445  using DecayedT = RemoveCVRef<QualDecayedTRef>;
446 
447  constexpr TargetType kTargetType =
456  // NOTE: We only use integers instead of enums as template parameters in
457  // order to work around a bug on C++14 under MSVC 2017.
458  // See b/236131881.
459  Initialize<static_cast<int>(kTargetType), QualDecayedTRef>(
460  std::forward<F>(f));
461  }
462 
463  // Note: QualTRef here includes the cv-ref qualifiers associated with the
464  // invocation of the Invocable. The unqualified type is the target object
465  // type to be stored.
466  template <class QualTRef, class... Args>
468  InitializeStorage<QualTRef>(std::forward<Args>(args)...);
469  }
470 
471  CoreImpl(CoreImpl&& other) noexcept {
472  other.manager_(FunctionToCall::relocate_from_to, &other.state_, &state_);
473  manager_ = other.manager_;
474  invoker_ = other.invoker_;
475  other.manager_ = EmptyManager;
476  other.invoker_ = nullptr;
477  }
478 
479  CoreImpl& operator=(CoreImpl&& other) noexcept {
480  // Put the left-hand operand in an empty state.
481  //
482  // Note: A full reset that leaves us with an object that has its invariants
483  // intact is necessary in order to handle self-move. This is required by
484  // types that are used with certain operations of the standard library, such
485  // as the default definition of std::swap when both operands target the same
486  // object.
487  Clear();
488 
489  // Perform the actual move/destory operation on the target function.
490  other.manager_(FunctionToCall::relocate_from_to, &other.state_, &state_);
491  manager_ = other.manager_;
492  invoker_ = other.invoker_;
493  other.manager_ = EmptyManager;
494  other.invoker_ = nullptr;
495 
496  return *this;
497  }
498 
500 
501  // Check whether or not the AnyInvocable is in the empty state.
502  bool HasValue() const { return invoker_ != nullptr; }
503 
504  // Effects: Puts the object into its empty state.
505  void Clear() {
508  invoker_ = nullptr;
509  }
510 
511  template <int target_type, class QualDecayedTRef, class F,
513  void Initialize(F&& f) {
514 // This condition handles types that decay into pointers, which includes
515 // function references. Since function references cannot be null, GCC warns
516 // against comparing their decayed form with nullptr.
517 // Since this is template-heavy code, we prefer to disable these warnings
518 // locally instead of adding yet another overload of this function.
519 #if !defined(__clang__) && defined(__GNUC__)
520 #pragma GCC diagnostic ignored "-Wpragmas"
521 #pragma GCC diagnostic ignored "-Waddress"
522 #pragma GCC diagnostic ignored "-Wnonnull-compare"
523 #pragma GCC diagnostic push
524 #endif
525  if (static_cast<RemoveCVRef<QualDecayedTRef>>(f) == nullptr) {
526 #if !defined(__clang__) && defined(__GNUC__)
527 #pragma GCC diagnostic pop
528 #endif
530  invoker_ = nullptr;
531  return;
532  }
533  InitializeStorage<QualDecayedTRef>(std::forward<F>(f));
534  }
535 
536  template <int target_type, class QualDecayedTRef, class F,
538  void Initialize(F&& f) {
539  // In this case we can "steal the guts" of the other AnyInvocable.
540  f.manager_(FunctionToCall::relocate_from_to, &f.state_, &state_);
541  manager_ = f.manager_;
542  invoker_ = f.invoker_;
543 
544  f.manager_ = EmptyManager;
545  f.invoker_ = nullptr;
546  }
547 
548  template <int target_type, class QualDecayedTRef, class F,
550  void Initialize(F&& f) {
551  if (f.HasValue()) {
552  InitializeStorage<QualDecayedTRef>(std::forward<F>(f));
553  } else {
555  invoker_ = nullptr;
556  }
557  }
558 
559  template <int target_type, class QualDecayedTRef, class F,
561  void Initialize(F&& f) {
562  InitializeStorage<QualDecayedTRef>(std::forward<F>(f));
563  }
564 
565  // Use local (inline) storage for applicable target object types.
566  template <class QualTRef, class... Args,
567  typename = absl::enable_if_t<
570  using RawT = RemoveCVRef<QualTRef>;
571  ::new (static_cast<void*>(&state_.storage))
572  RawT(std::forward<Args>(args)...);
573 
574  invoker_ = LocalInvoker<SigIsNoexcept, ReturnType, QualTRef, P...>;
575  // We can simplify our manager if we know the type is trivially copyable.
576  InitializeLocalManager<RawT>();
577  }
578 
579  // Use remote storage for target objects that cannot be stored locally.
580  template <class QualTRef, class... Args,
582  int> = 0>
584  InitializeRemoteManager<RemoveCVRef<QualTRef>>(std::forward<Args>(args)...);
585  // This is set after everything else in case an exception is thrown in an
586  // earlier step of the initialization.
587  invoker_ = RemoteInvoker<SigIsNoexcept, ReturnType, QualTRef, P...>;
588  }
589 
590  template <class T,
594  }
595 
596  template <class T,
599  manager_ = LocalManagerNontrivial<T>;
600  }
601 
602  template <class T>
605  alignof(T) <=
607 
608  template <class T, class... Args,
611  // unique_ptr is used for exception-safety in case construction throws.
612  std::unique_ptr<void, TrivialDeleter> uninitialized_target(
613  ::operator new(sizeof(T)), TrivialDeleter(sizeof(T)));
614  ::new (uninitialized_target.get()) T(std::forward<Args>(args)...);
615  state_.remote.target = uninitialized_target.release();
616  state_.remote.size = sizeof(T);
618  }
619 
620  template <class T, class... Args,
623  state_.remote.target = ::new T(std::forward<Args>(args)...);
624  manager_ = RemoteManagerNontrivial<T>;
625  }
626 
628  //
629  // Type trait to determine if the template argument is an AnyInvocable whose
630  // function type is compatible enough with ours such that we can
631  // "move the guts" out of it when moving, rather than having to place a new
632  // object into remote storage.
633 
634  template <typename Other>
636  static constexpr bool value = false;
637  };
638 
639  template <typename Sig>
641  static constexpr bool value =
642  (IsCompatibleConversion)(static_cast<
643  typename AnyInvocable<Sig>::CoreImpl*>(
644  nullptr),
645  static_cast<CoreImpl*>(nullptr));
646  };
647 
648  //
650 
653  InvokerType<SigIsNoexcept, ReturnType, P...>* invoker_;
654 };
655 
656 // A constructor name-tag used with Impl to request the
657 // conversion-constructor
659 
661 //
662 // A metafunction that is normally an identity metafunction except that when
663 // given a std::reference_wrapper<T>, it yields T&. This is necessary because
664 // currently std::reference_wrapper's operator() is not conditionally noexcept,
665 // so when checking if such an Invocable is nothrow-invocable, we must pull out
666 // the underlying type.
667 template <class T>
669  using type = T;
670 };
671 
672 template <class T>
673 struct UnwrapStdReferenceWrapperImpl<std::reference_wrapper<T>> {
674  using type = T&;
675 };
676 
677 template <class T>
680 //
682 
683 // An alias that always yields std::true_type (used with constraints) where
684 // substitution failures happen when forming the template arguments.
685 template <class... T>
686 using True =
687  std::integral_constant<bool, sizeof(absl::void_t<T...>*) != 0>;
688 
689 /*SFINAE constraints for the conversion-constructor.*/
690 template <class Sig, class F,
691  class = absl::enable_if_t<
692  !std::is_same<RemoveCVRef<F>, AnyInvocable<Sig>>::value>>
693 using CanConvert =
699 
700 /*SFINAE constraints for the std::in_place constructors.*/
701 template <class Sig, class F, class... Args>
702 using CanEmplace = True<
707 
708 /*SFINAE constraints for the conversion-assign operator.*/
709 template <class Sig, class F,
710  class = absl::enable_if_t<
711  !std::is_same<RemoveCVRef<F>, AnyInvocable<Sig>>::value>>
712 using CanAssign =
717 
718 /*SFINAE constraints for the reference-wrapper conversion-assign operator.*/
719 template <class Sig, class F>
722  Impl<Sig>::template CallIsValid<std::reference_wrapper<F>>::value>,
723  absl::enable_if_t<Impl<Sig>::template CallIsNoexceptIfSigIsNoexcept<
724  std::reference_wrapper<F>>::value>>;
725 
727 //
728 // The constraint for checking whether or not a call meets the noexcept
729 // callability requirements. This is a preprocessor macro because specifying it
730 // this way as opposed to a disjunction/branch can improve the user-side error
731 // messages and avoids an instantiation of std::is_nothrow_invocable_r in the
732 // cases where the user did not specify a noexcept function type.
733 //
734 #define ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT(inv_quals, noex) \
735  ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_##noex(inv_quals)
736 
737 // The disjunction below is because we can't rely on std::is_nothrow_invocable_r
738 // to give the right result when ReturnType is non-moveable in toolchains that
739 // don't treat non-moveable result types correctly. For example this was the
740 // case in libc++ before commit c3a24882 (2022-05).
741 #define ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_true(inv_quals) \
742  absl::enable_if_t<absl::disjunction< \
743  std::is_nothrow_invocable_r< \
744  ReturnType, UnwrapStdReferenceWrapper<absl::decay_t<F>> inv_quals, \
745  P...>, \
746  std::conjunction< \
747  std::is_nothrow_invocable< \
748  UnwrapStdReferenceWrapper<absl::decay_t<F>> inv_quals, P...>, \
749  std::is_same< \
750  ReturnType, \
751  absl::base_internal::invoke_result_t< \
752  UnwrapStdReferenceWrapper<absl::decay_t<F>> inv_quals, \
753  P...>>>>::value>
754 
755 #define ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_false(inv_quals)
756 //
758 
759 // A macro to generate partial specializations of Impl with the different
760 // combinations of supported cv/reference qualifiers and noexcept specifier.
761 //
762 // Here, `cv` are the cv-qualifiers if any, `ref` is the ref-qualifier if any,
763 // inv_quals is the reference type to be used when invoking the target, and
764 // noex is "true" if the function type is noexcept, or false if it is not.
765 //
766 // The CallIsValid condition is more complicated than simply using
767 // absl::base_internal::is_invocable_r because we can't rely on it to give the
768 // right result when ReturnType is non-moveable in toolchains that don't treat
769 // non-moveable result types correctly. For example this was the case in libc++
770 // before commit c3a24882 (2022-05).
771 #define ABSL_INTERNAL_ANY_INVOCABLE_IMPL_(cv, ref, inv_quals, noex) \
772  template <class ReturnType, class... P> \
773  class Impl<ReturnType(P...) cv ref ABSL_INTERNAL_NOEXCEPT_SPEC(noex)> \
774  : public CoreImpl<noex, ReturnType, P...> { \
775  public: \
776  /*The base class, which contains the datamembers and core operations*/ \
777  using Core = CoreImpl<noex, ReturnType, P...>; \
778  \
779  /*SFINAE constraint to check if F is invocable with the proper signature*/ \
780  template <class F> \
781  using CallIsValid = True<absl::enable_if_t<absl::disjunction< \
782  absl::base_internal::is_invocable_r<ReturnType, \
783  absl::decay_t<F> inv_quals, P...>, \
784  std::is_same<ReturnType, \
785  absl::base_internal::invoke_result_t< \
786  absl::decay_t<F> inv_quals, P...>>>::value>>; \
787  \
788  /*SFINAE constraint to check if F is nothrow-invocable when necessary*/ \
789  template <class F> \
790  using CallIsNoexceptIfSigIsNoexcept = \
791  True<ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT(inv_quals, \
792  noex)>; \
793  \
794  /*Put the AnyInvocable into an empty state.*/ \
795  Impl() = default; \
796  \
797  /*The implementation of a conversion-constructor from "f*/ \
798  /*This forwards to Core, attaching inv_quals so that the base class*/ \
799  /*knows how to properly type-erase the invocation.*/ \
800  template <class F> \
801  explicit Impl(ConversionConstruct, F&& f) \
802  : Core(TypedConversionConstruct< \
803  typename std::decay<F>::type inv_quals>(), \
804  std::forward<F>(f)) {} \
805  \
806  /*Forward along the in-place construction parameters.*/ \
807  template <class T, class... Args> \
808  explicit Impl(absl::in_place_type_t<T>, Args&&... args) \
809  : Core(absl::in_place_type<absl::decay_t<T> inv_quals>, \
810  std::forward<Args>(args)...) {} \
811  \
812  /*The actual invocation operation with the proper signature*/ \
813  ReturnType operator()(P... args) cv ref noexcept(noex) { \
814  assert(this->invoker_ != nullptr); \
815  return this->invoker_(const_cast<TypeErasedState*>(&this->state_), \
816  static_cast<ForwardedParameterType<P>>(args)...); \
817  } \
818  }
819 
820 // Define the `noexcept(true)` specialization only for C++17 and beyond, when
821 // `noexcept` is part of the type system.
822 #if ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
823 // A convenience macro that defines specializations for the noexcept(true) and
824 // noexcept(false) forms, given the other properties.
825 #define ABSL_INTERNAL_ANY_INVOCABLE_IMPL(cv, ref, inv_quals) \
826  ABSL_INTERNAL_ANY_INVOCABLE_IMPL_(cv, ref, inv_quals, false); \
827  ABSL_INTERNAL_ANY_INVOCABLE_IMPL_(cv, ref, inv_quals, true)
828 #else
829 #define ABSL_INTERNAL_ANY_INVOCABLE_IMPL(cv, ref, inv_quals) \
830  ABSL_INTERNAL_ANY_INVOCABLE_IMPL_(cv, ref, inv_quals, false)
831 #endif
832 
833 // Non-ref-qualified partial specializations
835 ABSL_INTERNAL_ANY_INVOCABLE_IMPL(const, , const&);
836 
837 // Lvalue-ref-qualified partial specializations
839 ABSL_INTERNAL_ANY_INVOCABLE_IMPL(const, &, const&);
840 
841 // Rvalue-ref-qualified partial specializations
843 ABSL_INTERNAL_ANY_INVOCABLE_IMPL(const, &&, const&&);
844 
845 // Undef the detail-only macros.
846 #undef ABSL_INTERNAL_ANY_INVOCABLE_IMPL
847 #undef ABSL_INTERNAL_ANY_INVOCABLE_IMPL_
848 #undef ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_false
849 #undef ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_true
850 #undef ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT
851 #undef ABSL_INTERNAL_NOEXCEPT_SPEC
852 
853 } // namespace internal_any_invocable
855 } // namespace absl
856 
857 #endif // ABSL_FUNCTIONAL_INTERNAL_ANY_INVOCABLE_H_
absl::internal_any_invocable::CoreImpl::CoreImpl
CoreImpl(TypedConversionConstruct< QualDecayedTRef >, F &&f)
Definition: internal/any_invocable.h:444
absl::internal_any_invocable::True
std::integral_constant< bool, sizeof(absl::void_t< T... > *) !=0 > True
Definition: internal/any_invocable.h:687
absl::internal_any_invocable::StorageProperty
StorageProperty
Definition: internal/any_invocable.h:91
absl::in_place_type_t
void(*)(utility_internal::InPlaceTypeTag< T >) in_place_type_t
Definition: abseil-cpp/absl/utility/utility.h:191
absl::internal_any_invocable::CoreImpl::TargetType
TargetType
Definition: internal/any_invocable.h:433
bool
bool
Definition: setup_once.h:312
absl::internal_any_invocable::Impl
Definition: internal/any_invocable.h:390
absl::internal_any_invocable::ForwardedParameter::type
decltype((ForwardImpl< T >)(std::integral_constant< bool, std::is_scalar< T >::value >())) type
Definition: internal/any_invocable.h:164
absl::internal_any_invocable::ABSL_INTERNAL_ANY_INVOCABLE_IMPL
ABSL_INTERNAL_ANY_INVOCABLE_IMPL(,, &)
absl::internal_any_invocable::CoreImpl::InitializeLocalManager
void InitializeLocalManager()
Definition: internal/any_invocable.h:592
absl::internal_any_invocable::CoreImpl::IsCompatibleAnyInvocable::value
static constexpr bool value
Definition: internal/any_invocable.h:636
google::protobuf.internal::true_type
integral_constant< bool, true > true_type
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/template_util.h:89
google::protobuf.internal::false_type
integral_constant< bool, false > false_type
Definition: bloaty/third_party/protobuf/src/google/protobuf/stubs/template_util.h:90
absl::internal_any_invocable::CoreImpl::Clear
void Clear()
Definition: internal/any_invocable.h:505
absl::internal_any_invocable::kAlignment
@ kAlignment
Definition: internal/any_invocable.h:92
absl::internal_any_invocable::TypeErasedState::remote
struct absl::internal_any_invocable::TypeErasedState::@68 remote
absl::internal_any_invocable::CoreImpl::operator=
CoreImpl & operator=(CoreImpl &&other) noexcept
Definition: internal/any_invocable.h:479
absl::internal_any_invocable::CoreImpl::TargetType::kIncompatibleAnyInvocable
@ kIncompatibleAnyInvocable
absl::internal_any_invocable::TypedConversionConstruct
Definition: internal/any_invocable.h:379
absl::enable_if_t
typename std::enable_if< B, T >::type enable_if_t
Definition: abseil-cpp/absl/meta/type_traits.h:631
to
size_t to
Definition: abseil-cpp/absl/container/internal/layout_test.cc:1385
absl::internal_any_invocable::ManagerType
void(FunctionToCall, TypeErasedState *, TypeErasedState *) ABSL_INTERNAL_NOEXCEPT_SPEC(true) ManagerType
Definition: internal/any_invocable.h:225
absl::internal_any_invocable::CanConvert
True< absl::enable_if_t<!IsInPlaceType< RemoveCVRef< F > >::value >, absl::enable_if_t< Impl< Sig >::template CallIsValid< F >::value >, absl::enable_if_t< Impl< Sig >::template CallIsNoexceptIfSigIsNoexcept< F >::value >, absl::enable_if_t< std::is_constructible< absl::decay_t< F >, F >::value > > CanConvert
Definition: internal/any_invocable.h:698
run_xds_tests.delete
delete
Definition: run_xds_tests.py:3329
absl::internal_any_invocable::ForwardedParameterType
typename ForwardedParameter< T >::type ForwardedParameterType
Definition: internal/any_invocable.h:168
env.new
def new
Definition: env.py:51
ABSL_NAMESPACE_END
#define ABSL_NAMESPACE_END
Definition: third_party/abseil-cpp/absl/base/config.h:171
absl::internal_any_invocable::RemoteManagerTrivial
void RemoteManagerTrivial(FunctionToCall operation, TypeErasedState *const from, TypeErasedState *const to) noexcept
Definition: internal/any_invocable.h:306
absl::internal_any_invocable::FunctionToCall::relocate_from_to
@ relocate_from_to
T
#define T(upbtypeconst, upbtype, ctype, default_value)
true
#define true
Definition: setup_once.h:324
absl::internal_any_invocable::IsCompatibleConversion
constexpr bool IsCompatibleConversion(void *, void *)
Definition: internal/any_invocable.h:417
absl::internal_any_invocable::LocalManagerNontrivial
void LocalManagerNontrivial(FunctionToCall operation, TypeErasedState *const from, TypeErasedState *const to) noexcept
Definition: internal/any_invocable.h:265
absl::internal_any_invocable::TrivialDeleter::operator()
void operator()(void *target) const
Definition: internal/any_invocable.h:410
from
size_t from
Definition: abseil-cpp/absl/container/internal/layout_test.cc:1384
ABSL_NAMESPACE_BEGIN
#define ABSL_NAMESPACE_BEGIN
Definition: third_party/abseil-cpp/absl/base/config.h:170
asyncio_get_stats.args
args
Definition: asyncio_get_stats.py:40
xds_interop_client.int
int
Definition: xds_interop_client.py:113
absl::internal_any_invocable::CanEmplace
True< absl::enable_if_t< Impl< Sig >::template CallIsValid< F >::value >, absl::enable_if_t< Impl< Sig >::template CallIsNoexceptIfSigIsNoexcept< F >::value >, absl::enable_if_t< std::is_constructible< absl::decay_t< F >, Args... >::value > > CanEmplace
Definition: internal/any_invocable.h:706
absl::move
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:221
hpack_encoder_fixtures::Args
Args({0, 16384})
absl::internal_any_invocable::CoreImpl::InitializeStorage
void InitializeStorage(Args &&... args)
Definition: internal/any_invocable.h:569
absl::internal_any_invocable::CoreImpl::invoker_
InvokerType< SigIsNoexcept, ReturnType, P... > * invoker_
Definition: internal/any_invocable.h:653
absl::internal_any_invocable::FunctionToCall::dispose
@ dispose
absl::internal_any_invocable::CoreImpl::CoreImpl
CoreImpl(CoreImpl &&other) noexcept
Definition: internal/any_invocable.h:471
absl::internal_any_invocable::UnwrapStdReferenceWrapperImpl::type
T type
Definition: internal/any_invocable.h:669
absl::internal_any_invocable::IsInPlaceType
Definition: internal/any_invocable.h:367
absl::internal_any_invocable::TypeErasedState
Definition: internal/any_invocable.h:182
absl::internal_any_invocable::RemoteManagerNontrivial
void RemoteManagerNontrivial(FunctionToCall operation, TypeErasedState *const from, TypeErasedState *const to) noexcept
Definition: internal/any_invocable.h:328
absl::internal_any_invocable::TrivialDeleter::TrivialDeleter
TrivialDeleter(std::size_t)
Definition: internal/any_invocable.h:408
absl::internal_any_invocable::CanAssign
True< absl::enable_if_t< Impl< Sig >::template CallIsValid< F >::value >, absl::enable_if_t< Impl< Sig >::template CallIsNoexceptIfSigIsNoexcept< F >::value >, absl::enable_if_t< std::is_constructible< absl::decay_t< F >, F >::value > > CanAssign
Definition: internal/any_invocable.h:716
absl::internal_any_invocable::ForwardImpl
T ForwardImpl(std::true_type)
absl::internal_any_invocable::InvokeR
void InvokeR(F &&f, P &&... args)
Definition: internal/any_invocable.h:129
absl::internal_any_invocable::CoreImpl::CoreImpl
CoreImpl() noexcept
Definition: internal/any_invocable.h:431
absl::internal_any_invocable::CoreImpl::Initialize
void Initialize(F &&f)
Definition: internal/any_invocable.h:513
absl::internal_any_invocable::RemoteInvoker
ReturnType RemoteInvoker(TypeErasedState *const state, ForwardedParameterType< P >... args) noexcept(SigIsNoexcept)
Definition: internal/any_invocable.h:349
absl::internal_any_invocable::UnwrapStdReferenceWrapperImpl< std::reference_wrapper< T > >::type
T & type
Definition: internal/any_invocable.h:674
absl::internal_any_invocable::ObjectInLocalStorage
T & ObjectInLocalStorage(TypeErasedState *const state)
Definition: internal/any_invocable.h:196
absl::internal_any_invocable::FunctionToCall
FunctionToCall
Definition: internal/any_invocable.h:178
F
#define F(b, c, d)
Definition: md4.c:112
absl::internal_any_invocable::CanAssignReferenceWrapper
True< absl::enable_if_t< Impl< Sig >::template CallIsValid< std::reference_wrapper< F > >::value >, absl::enable_if_t< Impl< Sig >::template CallIsNoexceptIfSigIsNoexcept< std::reference_wrapper< F > >::value > > CanAssignReferenceWrapper
Definition: internal/any_invocable.h:724
absl::internal_any_invocable::CoreImpl
Definition: internal/any_invocable.h:415
value
const char * value
Definition: hpack_parser_table.cc:165
absl::internal_any_invocable::CoreImpl::InitializeRemoteManager
void InitializeRemoteManager(Args &&... args)
Definition: internal/any_invocable.h:610
absl::internal_any_invocable::TypeErasedState::target
void * target
Definition: internal/any_invocable.h:185
absl::internal_any_invocable::CoreImpl::HasTrivialRemoteStorage
std::integral_constant< bool, std::is_trivially_destructible< T >::value &&alignof(T)<=ABSL_INTERNAL_DEFAULT_NEW_ALIGNMENT > HasTrivialRemoteStorage
Definition: internal/any_invocable.h:606
absl::void_t
typename type_traits_internal::VoidTImpl< Ts... >::type void_t
Definition: abseil-cpp/absl/meta/type_traits.h:218
absl::internal_any_invocable::CoreImpl::TargetType::kPointer
@ kPointer
P
Definition: miscompile_with_no_unique_address_test.cc:29
absl::internal_any_invocable::LocalManagerTrivial
void LocalManagerTrivial(FunctionToCall, TypeErasedState *const from, TypeErasedState *const to) noexcept
Definition: internal/any_invocable.h:240
absl::internal_any_invocable::RemoveCVRef
typename std::remove_cv< typename std::remove_reference< T >::type >::type RemoveCVRef
Definition: internal/any_invocable.h:119
size_
size_t size_
Definition: memory_allocator.cc:56
absl::internal_any_invocable::CoreImpl::state_
TypeErasedState state_
Definition: internal/any_invocable.h:651
ABSL_INTERNAL_UNREACHABLE
#define ABSL_INTERNAL_UNREACHABLE
Definition: abseil-cpp/absl/base/macros.h:155
absl::internal_any_invocable::UnwrapStdReferenceWrapperImpl
Definition: internal/any_invocable.h:668
std
Definition: grpcpp/impl/codegen/async_unary_call.h:407
absl::internal_any_invocable::TypeErasedState::storage
char storage[kStorageSize]
Definition: internal/any_invocable.h:191
absl::internal_any_invocable::kStorageSize
@ kStorageSize
Definition: internal/any_invocable.h:93
state
Definition: bloaty/third_party/zlib/contrib/blast/blast.c:41
absl::internal_any_invocable::CoreImpl::CoreImpl
CoreImpl(absl::in_place_type_t< QualTRef >, Args &&... args)
Definition: internal/any_invocable.h:467
ABSL_INTERNAL_NOEXCEPT_SPEC
#define ABSL_INTERNAL_NOEXCEPT_SPEC(noex)
Definition: internal/any_invocable.h:81
absl::internal_any_invocable::IsAnyInvocable
Definition: internal/any_invocable.h:101
absl::internal_any_invocable::ConversionConstruct
Definition: internal/any_invocable.h:658
absl::internal_any_invocable::CoreImpl::manager_
ManagerType * manager_
Definition: internal/any_invocable.h:652
absl::AnyInvocable
Definition: any_invocable.h:152
absl::internal_any_invocable::CoreImpl::result_type
ReturnType result_type
Definition: internal/any_invocable.h:429
absl::internal_any_invocable::LocalInvoker
ReturnType LocalInvoker(TypeErasedState *const state, ForwardedParameterType< P >... args) noexcept(SigIsNoexcept)
Definition: internal/any_invocable.h:291
absl::internal_any_invocable::CoreImpl::HasValue
bool HasValue() const
Definition: internal/any_invocable.h:502
absl
Definition: abseil-cpp/absl/algorithm/algorithm.h:31
asyncio_get_stats.type
type
Definition: asyncio_get_stats.py:37
absl::internal_any_invocable::CoreImpl::~CoreImpl
~CoreImpl()
Definition: internal/any_invocable.h:499
setup.template
template
Definition: setup.py:47
size
voidpf void uLong size
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
absl::internal_any_invocable::IsStoredLocally
std::integral_constant< bool, sizeof(T)<=kStorageSize &&alignof(T)<=kAlignment &&kAlignment % alignof(T)==0 &&std::is_nothrow_move_constructible< T >::value > IsStoredLocally
Definition: internal/any_invocable.h:114
absl::internal_any_invocable::TypeErasedState::size
std::size_t size
Definition: internal/any_invocable.h:187
absl::internal_any_invocable::CoreImpl::IsCompatibleAnyInvocable
Definition: internal/any_invocable.h:635
absl::internal_any_invocable::EmptyManager
void EmptyManager(FunctionToCall, TypeErasedState *, TypeErasedState *) noexcept
Definition: internal/any_invocable.h:234
absl::internal_any_invocable::UnwrapStdReferenceWrapper
typename UnwrapStdReferenceWrapperImpl< T >::type UnwrapStdReferenceWrapper
Definition: internal/any_invocable.h:679
absl::internal_any_invocable::ForwardedParameter
Definition: internal/any_invocable.h:161
absl::internal_any_invocable::InvokerType
ReturnType(TypeErasedState *, ForwardedParameterType< P >...) ABSL_INTERNAL_NOEXCEPT_SPEC(SigIsNoexcept) InvokerType
Definition: internal/any_invocable.h:231
ABSL_FALLTHROUGH_INTENDED
#define ABSL_FALLTHROUGH_INTENDED
Definition: abseil-cpp/absl/base/attributes.h:641
grpc_core::P
std::function< Poll< absl::StatusOr< T > >()> P
Definition: try_join_test.cc:27
absl::internal_any_invocable::CoreImpl::TargetType::kCompatibleAnyInvocable
@ kCompatibleAnyInvocable
setup.target
target
Definition: third_party/bloaty/third_party/protobuf/python/setup.py:179
absl::internal_any_invocable::TrivialDeleter
Definition: internal/any_invocable.h:406
ABSL_INTERNAL_DEFAULT_NEW_ALIGNMENT
#define ABSL_INTERNAL_DEFAULT_NEW_ALIGNMENT
Definition: abseil-cpp/absl/meta/type_traits.h:55
absl::internal_any_invocable::CoreImpl::TargetType::kOther
@ kOther
absl::base_internal::invoke
invoke_result_t< F, Args... > invoke(F &&f, Args &&... args)
Definition: abseil-cpp/absl/base/internal/invoke.h:211


grpc
Author(s):
autogenerated on Fri May 16 2025 02:57:41