• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
20 ////////////////////////////////////////////////////////////////////////////////
21 //                                                                            //
22 // This implementation chooses between local storage and remote storage for   //
23 // the contained target object based on the target object's size, alignment   //
24 // requirements, and whether or not it has a nothrow move constructor.        //
25 // Additional optimizations are performed when the object is a trivially      //
26 // 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 //                                                                            //
52 ////////////////////////////////////////////////////////////////////////////////
53 
54 // IWYU pragma: private, include "absl/functional/any_invocable.h"
55 
56 #include <cassert>
57 #include <cstddef>
58 #include <cstring>
59 #include <exception>
60 #include <functional>
61 #include <memory>
62 #include <new>
63 #include <type_traits>
64 #include <utility>
65 
66 #include "absl/base/attributes.h"
67 #include "absl/base/config.h"
68 #include "absl/base/macros.h"
69 #include "absl/base/optimization.h"
70 #include "absl/meta/type_traits.h"
71 #include "absl/utility/utility.h"
72 
73 namespace absl {
74 ABSL_NAMESPACE_BEGIN
75 
76 // Defined in functional/any_invocable.h
77 template <class Sig>
78 class AnyInvocable;
79 
80 namespace internal_any_invocable {
81 
82 // Constants relating to the small-object-storage for AnyInvocable
83 enum StorageProperty : std::size_t {
84   kAlignment = alignof(std::max_align_t),  // The alignment of the storage
85   kStorageSize = sizeof(void*) * 2         // The size of the storage
86 };
87 
88 ////////////////////////////////////////////////////////////////////////////////
89 //
90 // A metafunction for checking if a type is an AnyInvocable instantiation.
91 // This is used during conversion operations.
92 template <class T>
93 struct IsAnyInvocable : std::false_type {};
94 
95 template <class Sig>
96 struct IsAnyInvocable<AnyInvocable<Sig>> : std::true_type {};
97 //
98 ////////////////////////////////////////////////////////////////////////////////
99 
100 // A metafunction that tells us whether or not a target function type should be
101 // stored locally in the small object optimization storage
102 template <class T>
103 constexpr bool IsStoredLocally() {
104   if constexpr (sizeof(T) <= kStorageSize && alignof(T) <= kAlignment &&
105                 kAlignment % alignof(T) == 0) {
106     return std::is_nothrow_move_constructible<T>::value;
107   }
108   return false;
109 }
110 
111 // An implementation of std::remove_cvref_t of C++20.
112 template <class T>
113 using RemoveCVRef =
114     typename std::remove_cv<typename std::remove_reference<T>::type>::type;
115 
116 // An implementation of std::invoke_r of C++23.
117 template <class ReturnType, class F, class... P>
118 ReturnType InvokeR(F&& f, P&&... args) {
119   if constexpr (std::is_void_v<ReturnType>) {
120     std::invoke(std::forward<F>(f), std::forward<P>(args)...);
121   } else {
122     return std::invoke(std::forward<F>(f), std::forward<P>(args)...);
123   }
124 }
125 
126 //
127 ////////////////////////////////////////////////////////////////////////////////
128 
129 ////////////////////////////////////////////////////////////////////////////////
130 ///
131 // A metafunction that takes a "T" corresponding to a parameter type of the
132 // user's specified function type, and yields the parameter type to use for the
133 // type-erased invoker. In order to prevent observable moves, this must be
134 // either a reference or, if the type is trivial, the original parameter type
135 // itself. Since the parameter type may be incomplete at the point that this
136 // metafunction is used, we can only do this optimization for scalar types
137 // rather than for any trivial type.
138 template <typename T>
139 T ForwardImpl(std::true_type);
140 
141 template <typename T>
142 T&& ForwardImpl(std::false_type);
143 
144 // NOTE: We deliberately use an intermediate struct instead of a direct alias,
145 // as a workaround for b/206991861 on MSVC versions < 1924.
146 template <class T>
147 struct ForwardedParameter {
148   using type = decltype((
149       ForwardImpl<T>)(std::integral_constant<bool,
150                                              std::is_scalar<T>::value>()));
151 };
152 
153 template <class T>
154 using ForwardedParameterType = typename ForwardedParameter<T>::type;
155 //
156 ////////////////////////////////////////////////////////////////////////////////
157 
158 // A discriminator when calling the "manager" function that describes operation
159 // type-erased operation should be invoked.
160 //
161 // "relocate_from_to" specifies that the manager should perform a move.
162 //
163 // "dispose" specifies that the manager should perform a destroy.
164 enum class FunctionToCall : bool { relocate_from_to, dispose };
165 
166 // The portion of `AnyInvocable` state that contains either a pointer to the
167 // target object or the object itself in local storage
168 union TypeErasedState {
169   struct {
170     // A pointer to the type-erased object when remotely stored
171     void* target;
172     // The size of the object for `RemoteManagerTrivial`
173     std::size_t size;
174   } remote;
175 
176   // Local-storage for the type-erased object when small and trivial enough
177   alignas(kAlignment) char storage[kStorageSize];
178 };
179 
180 // A typed accessor for the object in `TypeErasedState` storage
181 template <class T>
182 T& ObjectInLocalStorage(TypeErasedState* const state) {
183   // We launder here because the storage may be reused with the same type.
184   return *std::launder(reinterpret_cast<T*>(&state->storage));
185 }
186 
187 // The type for functions issuing lifetime-related operations: move and dispose
188 // A pointer to such a function is contained in each `AnyInvocable` instance.
189 // NOTE: When specifying `FunctionToCall::`dispose, the same state must be
190 // passed as both "from" and "to".
191 using ManagerType = void(FunctionToCall /*operation*/,
192                          TypeErasedState* /*from*/,
193                          TypeErasedState* /*to*/) noexcept(true);
194 
195 // The type for functions issuing the actual invocation of the object
196 // A pointer to such a function is contained in each AnyInvocable instance.
197 template <bool SigIsNoexcept, class ReturnType, class... P>
198 using InvokerType = ReturnType(
199     TypeErasedState*, ForwardedParameterType<P>...) noexcept(SigIsNoexcept);
200 
201 // The manager that is used when AnyInvocable is empty
202 inline void EmptyManager(FunctionToCall /*operation*/,
203                          TypeErasedState* /*from*/,
204                          TypeErasedState* /*to*/) noexcept {}
205 
206 // The manager that is used when a target function is in local storage and is
207 // a trivially copyable type.
208 inline void LocalManagerTrivial(FunctionToCall /*operation*/,
209                                 TypeErasedState* const from,
210                                 TypeErasedState* const to) noexcept {
211   // This single statement without branching handles both possible operations.
212   //
213   // For FunctionToCall::dispose, "from" and "to" point to the same state, and
214   // so this assignment logically would do nothing.
215   //
216   // Note: Correctness here relies on http://wg21.link/p0593, which has only
217   // become standard in C++20, though implementations do not break it in
218   // practice for earlier versions of C++.
219   //
220   // The correct way to do this without that paper is to first placement-new a
221   // default-constructed T in "to->storage" prior to the memmove, but doing so
222   // requires a different function to be created for each T that is stored
223   // locally, which can cause unnecessary bloat and be less cache friendly.
224   *to = *from;
225 
226   // Note: Because the type is trivially copyable, the destructor does not need
227   // to be called ("trivially copyable" requires a trivial destructor).
228 }
229 
230 // The manager that is used when a target function is in local storage and is
231 // not a trivially copyable type.
232 template <class T>
233 void LocalManagerNontrivial(FunctionToCall operation,
234                             TypeErasedState* const from,
235                             TypeErasedState* const to) noexcept {
236   static_assert(IsStoredLocally<T>(),
237                 "Local storage must only be used for supported types.");
238   static_assert(!std::is_trivially_copyable<T>::value,
239                 "Locally stored types must be trivially copyable.");
240 
241   T& from_object = (ObjectInLocalStorage<T>)(from);
242 
243   switch (operation) {
244     case FunctionToCall::relocate_from_to:
245       // NOTE: Requires that the left-hand operand is already empty.
246       ::new (static_cast<void*>(&to->storage)) T(std::move(from_object));
247       ABSL_FALLTHROUGH_INTENDED;
248     case FunctionToCall::dispose:
249       from_object.~T();  // Must not throw. // NOLINT
250       return;
251   }
252   ABSL_UNREACHABLE();
253 }
254 
255 // The invoker that is used when a target function is in local storage
256 // Note: QualTRef here is the target function type along with cv and reference
257 // qualifiers that must be used when calling the function.
258 template <bool SigIsNoexcept, class ReturnType, class QualTRef, class... P>
259 ReturnType LocalInvoker(
260     TypeErasedState* const state,
261     ForwardedParameterType<P>... args) noexcept(SigIsNoexcept) {
262   using RawT = RemoveCVRef<QualTRef>;
263   static_assert(
264       IsStoredLocally<RawT>(),
265       "Target object must be in local storage in order to be invoked from it.");
266 
267   auto& f = (ObjectInLocalStorage<RawT>)(state);
268   return (InvokeR<ReturnType>)(static_cast<QualTRef>(f),
269                                static_cast<ForwardedParameterType<P>>(args)...);
270 }
271 
272 // The manager that is used when a target function is in remote storage and it
273 // has a trivial destructor
274 inline void RemoteManagerTrivial(FunctionToCall operation,
275                                  TypeErasedState* const from,
276                                  TypeErasedState* const to) noexcept {
277   switch (operation) {
278     case FunctionToCall::relocate_from_to:
279       // NOTE: Requires that the left-hand operand is already empty.
280       to->remote = from->remote;
281       return;
282     case FunctionToCall::dispose:
283 #if defined(__cpp_sized_deallocation)
284       ::operator delete(from->remote.target, from->remote.size);
285 #else   // __cpp_sized_deallocation
286       ::operator delete(from->remote.target);
287 #endif  // __cpp_sized_deallocation
288       return;
289   }
290   ABSL_UNREACHABLE();
291 }
292 
293 // The manager that is used when a target function is in remote storage and the
294 // destructor of the type is not trivial
295 template <class T>
296 void RemoteManagerNontrivial(FunctionToCall operation,
297                              TypeErasedState* const from,
298                              TypeErasedState* const to) noexcept {
299   static_assert(!IsStoredLocally<T>(),
300                 "Remote storage must only be used for types that do not "
301                 "qualify for local storage.");
302 
303   switch (operation) {
304     case FunctionToCall::relocate_from_to:
305       // NOTE: Requires that the left-hand operand is already empty.
306       to->remote.target = from->remote.target;
307       return;
308     case FunctionToCall::dispose:
309       ::delete static_cast<T*>(from->remote.target);  // Must not throw.
310       return;
311   }
312   ABSL_UNREACHABLE();
313 }
314 
315 // The invoker that is used when a target function is in remote storage
316 template <bool SigIsNoexcept, class ReturnType, class QualTRef, class... P>
317 ReturnType RemoteInvoker(
318     TypeErasedState* const state,
319     ForwardedParameterType<P>... args) noexcept(SigIsNoexcept) {
320   using RawT = RemoveCVRef<QualTRef>;
321   static_assert(!IsStoredLocally<RawT>(),
322                 "Target object must be in remote storage in order to be "
323                 "invoked from it.");
324 
325   auto& f = *static_cast<RawT*>(state->remote.target);
326   return (InvokeR<ReturnType>)(static_cast<QualTRef>(f),
327                                static_cast<ForwardedParameterType<P>>(args)...);
328 }
329 
330 ////////////////////////////////////////////////////////////////////////////////
331 //
332 // A metafunction that checks if a type T is an instantiation of
333 // absl::in_place_type_t (needed for constructor constraints of AnyInvocable).
334 template <class T>
335 struct IsInPlaceType : std::false_type {};
336 
337 template <class T>
338 struct IsInPlaceType<absl::in_place_type_t<T>> : std::true_type {};
339 //
340 ////////////////////////////////////////////////////////////////////////////////
341 
342 // A constructor name-tag used with CoreImpl (below) to request the
343 // conversion-constructor. QualDecayedTRef is the decayed-type of the object to
344 // wrap, along with the cv and reference qualifiers that must be applied when
345 // performing an invocation of the wrapped object.
346 template <class QualDecayedTRef>
347 struct TypedConversionConstruct {};
348 
349 // A helper base class for all core operations of AnyInvocable. Most notably,
350 // this class creates the function call operator and constraint-checkers so that
351 // the top-level class does not have to be a series of partial specializations.
352 //
353 // Note: This definition exists (as opposed to being a declaration) so that if
354 // the user of the top-level template accidentally passes a template argument
355 // that is not a function type, they will get a static_assert in AnyInvocable's
356 // class body rather than an error stating that Impl is not defined.
357 template <class Sig>
358 class Impl {};  // Note: This is partially-specialized later.
359 
360 // A std::unique_ptr deleter that deletes memory allocated via ::operator new.
361 #if defined(__cpp_sized_deallocation)
362 class TrivialDeleter {
363  public:
364   explicit TrivialDeleter(std::size_t size) : size_(size) {}
365 
366   void operator()(void* target) const {
367     ::operator delete(target, size_);
368   }
369 
370  private:
371   std::size_t size_;
372 };
373 #else   // __cpp_sized_deallocation
374 class TrivialDeleter {
375  public:
376   explicit TrivialDeleter(std::size_t) {}
377 
378   void operator()(void* target) const { ::operator delete(target); }
379 };
380 #endif  // __cpp_sized_deallocation
381 
382 template <bool SigIsNoexcept, class ReturnType, class... P>
383 class CoreImpl;
384 
385 constexpr bool IsCompatibleConversion(void*, void*) { return false; }
386 template <bool NoExceptSrc, bool NoExceptDest, class... T>
387 constexpr bool IsCompatibleConversion(CoreImpl<NoExceptSrc, T...>*,
388                                       CoreImpl<NoExceptDest, T...>*) {
389   return !NoExceptDest || NoExceptSrc;
390 }
391 
392 // A helper base class for all core operations of AnyInvocable that do not
393 // depend on the cv/ref qualifiers of the function type.
394 template <bool SigIsNoexcept, class ReturnType, class... P>
395 class CoreImpl {
396  public:
397   using result_type = ReturnType;
398 
399   CoreImpl() noexcept : manager_(EmptyManager), invoker_(nullptr) {}
400 
401   // Note: QualDecayedTRef here includes the cv-ref qualifiers associated with
402   // the invocation of the Invocable. The unqualified type is the target object
403   // type to be stored.
404   template <class QualDecayedTRef, class F>
405   explicit CoreImpl(TypedConversionConstruct<QualDecayedTRef>, F&& f) {
406     using DecayedT = RemoveCVRef<QualDecayedTRef>;
407 
408     if constexpr (std::is_pointer<DecayedT>::value ||
409                   std::is_member_pointer<DecayedT>::value) {
410       // This condition handles types that decay into pointers. This includes
411       // function references, which cannot be null. GCC warns against comparing
412       // their decayed form with nullptr (https://godbolt.org/z/9r9TMTcPK).
413       // We could work around this warning with constexpr programming, using
414       // std::is_function_v<std::remove_reference_t<F>>, but we choose to ignore
415       // it instead of writing more code.
416 #if !defined(__clang__) && defined(__GNUC__)
417 #pragma GCC diagnostic push
418 #pragma GCC diagnostic ignored "-Wpragmas"
419 #pragma GCC diagnostic ignored "-Waddress"
420 #pragma GCC diagnostic ignored "-Wnonnull-compare"
421 #endif
422       if (static_cast<DecayedT>(f) == nullptr) {
423 #if !defined(__clang__) && defined(__GNUC__)
424 #pragma GCC diagnostic pop
425 #endif
426         manager_ = EmptyManager;
427         invoker_ = nullptr;
428       } else {
429         InitializeStorage<QualDecayedTRef>(std::forward<F>(f));
430       }
431     } else if constexpr (IsCompatibleAnyInvocable<DecayedT>::value) {
432       // In this case we can "steal the guts" of the other AnyInvocable.
433       f.manager_(FunctionToCall::relocate_from_to, &f.state_, &state_);
434       manager_ = f.manager_;
435       invoker_ = f.invoker_;
436 
437       f.manager_ = EmptyManager;
438       f.invoker_ = nullptr;
439     } else if constexpr (IsAnyInvocable<DecayedT>::value) {
440       if (f.HasValue()) {
441         InitializeStorage<QualDecayedTRef>(std::forward<F>(f));
442       } else {
443         manager_ = EmptyManager;
444         invoker_ = nullptr;
445       }
446     } else {
447       InitializeStorage<QualDecayedTRef>(std::forward<F>(f));
448     }
449   }
450 
451   // Note: QualTRef here includes the cv-ref qualifiers associated with the
452   // invocation of the Invocable. The unqualified type is the target object
453   // type to be stored.
454   template <class QualTRef, class... Args>
455   explicit CoreImpl(absl::in_place_type_t<QualTRef>, Args&&... args) {
456     InitializeStorage<QualTRef>(std::forward<Args>(args)...);
457   }
458 
459   CoreImpl(CoreImpl&& other) noexcept {
460     other.manager_(FunctionToCall::relocate_from_to, &other.state_, &state_);
461     manager_ = other.manager_;
462     invoker_ = other.invoker_;
463     other.manager_ = EmptyManager;
464     other.invoker_ = nullptr;
465   }
466 
467   CoreImpl& operator=(CoreImpl&& other) noexcept {
468     // Put the left-hand operand in an empty state.
469     //
470     // Note: A full reset that leaves us with an object that has its invariants
471     // intact is necessary in order to handle self-move. This is required by
472     // types that are used with certain operations of the standard library, such
473     // as the default definition of std::swap when both operands target the same
474     // object.
475     Clear();
476 
477     // Perform the actual move/destroy operation on the target function.
478     other.manager_(FunctionToCall::relocate_from_to, &other.state_, &state_);
479     manager_ = other.manager_;
480     invoker_ = other.invoker_;
481     other.manager_ = EmptyManager;
482     other.invoker_ = nullptr;
483 
484     return *this;
485   }
486 
487   ~CoreImpl() { manager_(FunctionToCall::dispose, &state_, &state_); }
488 
489   // Check whether or not the AnyInvocable is in the empty state.
490   bool HasValue() const { return invoker_ != nullptr; }
491 
492   // Effects: Puts the object into its empty state.
493   void Clear() {
494     manager_(FunctionToCall::dispose, &state_, &state_);
495     manager_ = EmptyManager;
496     invoker_ = nullptr;
497   }
498 
499   // Use local (inline) storage for applicable target object types.
500   template <class QualTRef, class... Args>
501   void InitializeStorage(Args&&... args) {
502     using RawT = RemoveCVRef<QualTRef>;
503     if constexpr (IsStoredLocally<RawT>()) {
504       ::new (static_cast<void*>(&state_.storage))
505           RawT(std::forward<Args>(args)...);
506       invoker_ = LocalInvoker<SigIsNoexcept, ReturnType, QualTRef, P...>;
507       // We can simplify our manager if we know the type is trivially copyable.
508       if constexpr (std::is_trivially_copyable_v<RawT>) {
509         manager_ = LocalManagerTrivial;
510       } else {
511         manager_ = LocalManagerNontrivial<RawT>;
512       }
513     } else {
514       InitializeRemoteManager<RawT>(std::forward<Args>(args)...);
515       // This is set after everything else in case an exception is thrown in an
516       // earlier step of the initialization.
517       invoker_ = RemoteInvoker<SigIsNoexcept, ReturnType, QualTRef, P...>;
518     }
519   }
520 
521   template <class T, class... Args>
522   void InitializeRemoteManager(Args&&... args) {
523     if constexpr (std::is_trivially_destructible_v<T> &&
524                   alignof(T) <= ABSL_INTERNAL_DEFAULT_NEW_ALIGNMENT) {
525       // unique_ptr is used for exception-safety in case construction throws.
526       std::unique_ptr<void, TrivialDeleter> uninitialized_target(
527           ::operator new(sizeof(T)), TrivialDeleter(sizeof(T)));
528       ::new (uninitialized_target.get()) T(std::forward<Args>(args)...);
529       state_.remote.target = uninitialized_target.release();
530       state_.remote.size = sizeof(T);
531       manager_ = RemoteManagerTrivial;
532     } else {
533       state_.remote.target = ::new T(std::forward<Args>(args)...);
534       manager_ = RemoteManagerNontrivial<T>;
535     }
536   }
537 
538   //////////////////////////////////////////////////////////////////////////////
539   //
540   // Type trait to determine if the template argument is an AnyInvocable whose
541   // function type is compatible enough with ours such that we can
542   // "move the guts" out of it when moving, rather than having to place a new
543   // object into remote storage.
544 
545   template <typename Other>
546   struct IsCompatibleAnyInvocable {
547     static constexpr bool value = false;
548   };
549 
550   template <typename Sig>
551   struct IsCompatibleAnyInvocable<AnyInvocable<Sig>> {
552     static constexpr bool value =
553         (IsCompatibleConversion)(static_cast<
554                                      typename AnyInvocable<Sig>::CoreImpl*>(
555                                      nullptr),
556                                  static_cast<CoreImpl*>(nullptr));
557   };
558 
559   //
560   //////////////////////////////////////////////////////////////////////////////
561 
562   TypeErasedState state_;
563   ManagerType* manager_;
564   InvokerType<SigIsNoexcept, ReturnType, P...>* invoker_;
565 };
566 
567 // A constructor name-tag used with Impl to request the
568 // conversion-constructor
569 struct ConversionConstruct {};
570 
571 ////////////////////////////////////////////////////////////////////////////////
572 //
573 // A metafunction that is normally an identity metafunction except that when
574 // given a std::reference_wrapper<T>, it yields T&. This is necessary because
575 // currently std::reference_wrapper's operator() is not conditionally noexcept,
576 // so when checking if such an Invocable is nothrow-invocable, we must pull out
577 // the underlying type.
578 template <class T>
579 struct UnwrapStdReferenceWrapperImpl {
580   using type = T;
581 };
582 
583 template <class T>
584 struct UnwrapStdReferenceWrapperImpl<std::reference_wrapper<T>> {
585   using type = T&;
586 };
587 
588 template <class T>
589 using UnwrapStdReferenceWrapper =
590     typename UnwrapStdReferenceWrapperImpl<T>::type;
591 //
592 ////////////////////////////////////////////////////////////////////////////////
593 
594 // An alias that always yields std::true_type (used with constraints) where
595 // substitution failures happen when forming the template arguments.
596 template <class... T>
597 using TrueAlias =
598     std::integral_constant<bool, sizeof(absl::void_t<T...>*) != 0>;
599 
600 /*SFINAE constraints for the conversion-constructor.*/
601 template <class Sig, class F,
602           class = absl::enable_if_t<
603               !std::is_same<RemoveCVRef<F>, AnyInvocable<Sig>>::value>>
604 using CanConvert = TrueAlias<
605     absl::enable_if_t<!IsInPlaceType<RemoveCVRef<F>>::value>,
606     absl::enable_if_t<Impl<Sig>::template CallIsValid<F>::value>,
607     absl::enable_if_t<
608         Impl<Sig>::template CallIsNoexceptIfSigIsNoexcept<F>::value>,
609     absl::enable_if_t<std::is_constructible<absl::decay_t<F>, F>::value>>;
610 
611 /*SFINAE constraints for the std::in_place constructors.*/
612 template <class Sig, class F, class... Args>
613 using CanEmplace = TrueAlias<
614     absl::enable_if_t<Impl<Sig>::template CallIsValid<F>::value>,
615     absl::enable_if_t<
616         Impl<Sig>::template CallIsNoexceptIfSigIsNoexcept<F>::value>,
617     absl::enable_if_t<std::is_constructible<absl::decay_t<F>, Args...>::value>>;
618 
619 /*SFINAE constraints for the conversion-assign operator.*/
620 template <class Sig, class F,
621           class = absl::enable_if_t<
622               !std::is_same<RemoveCVRef<F>, AnyInvocable<Sig>>::value>>
623 using CanAssign = TrueAlias<
624     absl::enable_if_t<Impl<Sig>::template CallIsValid<F>::value>,
625     absl::enable_if_t<
626         Impl<Sig>::template CallIsNoexceptIfSigIsNoexcept<F>::value>,
627     absl::enable_if_t<std::is_constructible<absl::decay_t<F>, F>::value>>;
628 
629 /*SFINAE constraints for the reference-wrapper conversion-assign operator.*/
630 template <class Sig, class F>
631 using CanAssignReferenceWrapper = TrueAlias<
632     absl::enable_if_t<
633         Impl<Sig>::template CallIsValid<std::reference_wrapper<F>>::value>,
634     absl::enable_if_t<Impl<Sig>::template CallIsNoexceptIfSigIsNoexcept<
635         std::reference_wrapper<F>>::value>>;
636 
637 // The constraint for checking whether or not a call meets the noexcept
638 // callability requirements. We use a preprocessor macro because specifying it
639 // this way as opposed to a disjunction/branch can improve the user-side error
640 // messages and avoids an instantiation of std::is_nothrow_invocable_r in the
641 // cases where the user did not specify a noexcept function type.
642 //
643 // The disjunction below is because we can't rely on std::is_nothrow_invocable_r
644 // to give the right result when ReturnType is non-moveable in toolchains that
645 // don't treat non-moveable result types correctly. For example this was the
646 // case in libc++ before commit c3a24882 (2022-05).
647 #define ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_true(inv_quals)      \
648   absl::enable_if_t<absl::disjunction<                                       \
649       std::is_nothrow_invocable_r<                                           \
650           ReturnType, UnwrapStdReferenceWrapper<absl::decay_t<F>> inv_quals, \
651           P...>,                                                             \
652       std::conjunction<                                                      \
653           std::is_nothrow_invocable<                                         \
654               UnwrapStdReferenceWrapper<absl::decay_t<F>> inv_quals, P...>,  \
655           std::is_same<                                                      \
656               ReturnType,                                                    \
657               std::invoke_result_t<                                          \
658                   UnwrapStdReferenceWrapper<absl::decay_t<F>> inv_quals,     \
659                   P...>>>>::value>
660 
661 #define ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_false(inv_quals)
662 //
663 ////////////////////////////////////////////////////////////////////////////////
664 
665 // A macro to generate partial specializations of Impl with the different
666 // combinations of supported cv/reference qualifiers and noexcept specifier.
667 //
668 // Here, `cv` are the cv-qualifiers if any, `ref` is the ref-qualifier if any,
669 // inv_quals is the reference type to be used when invoking the target, and
670 // noex is "true" if the function type is noexcept, or false if it is not.
671 //
672 // The CallIsValid condition is more complicated than simply using
673 // std::is_invocable_r because we can't rely on it to give the right result
674 // when ReturnType is non-moveable in toolchains that don't treat non-moveable
675 // result types correctly. For example this was the case in libc++ before commit
676 // c3a24882 (2022-05).
677 #define ABSL_INTERNAL_ANY_INVOCABLE_IMPL_(cv, ref, inv_quals, noex)            \
678   template <class ReturnType, class... P>                                      \
679   class Impl<ReturnType(P...) cv ref noexcept(noex)>                           \
680       : public CoreImpl<noex, ReturnType, P...> {                              \
681    public:                                                                     \
682     /*The base class, which contains the datamembers and core operations*/     \
683     using Core = CoreImpl<noex, ReturnType, P...>;                             \
684                                                                                \
685     /*SFINAE constraint to check if F is invocable with the proper signature*/ \
686     template <class F>                                                         \
687     using CallIsValid = TrueAlias<absl::enable_if_t<absl::disjunction<         \
688         std::is_invocable_r<ReturnType, absl::decay_t<F> inv_quals, P...>,     \
689         std::is_same<                                                          \
690             ReturnType,                                                        \
691             std::invoke_result_t<absl::decay_t<F> inv_quals, P...>>>::value>>; \
692                                                                                \
693     /*SFINAE constraint to check if F is nothrow-invocable when necessary*/    \
694     template <class F>                                                         \
695     using CallIsNoexceptIfSigIsNoexcept =                                      \
696         TrueAlias<ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_##noex(      \
697             inv_quals)>;                                                       \
698                                                                                \
699     /*Put the AnyInvocable into an empty state.*/                              \
700     Impl() = default;                                                          \
701                                                                                \
702     /*The implementation of a conversion-constructor from "f*/                 \
703     /*This forwards to Core, attaching inv_quals so that the base class*/      \
704     /*knows how to properly type-erase the invocation.*/                       \
705     template <class F>                                                         \
706     explicit Impl(ConversionConstruct, F&& f)                                  \
707         : Core(TypedConversionConstruct<                                       \
708                    typename std::decay<F>::type inv_quals>(),                  \
709                std::forward<F>(f)) {}                                          \
710                                                                                \
711     /*Forward along the in-place construction parameters.*/                    \
712     template <class T, class... Args>                                          \
713     explicit Impl(absl::in_place_type_t<T>, Args&&... args)                    \
714         : Core(absl::in_place_type<absl::decay_t<T> inv_quals>,                \
715                std::forward<Args>(args)...) {}                                 \
716                                                                                \
717     /*Raises a fatal error when the AnyInvocable is invoked after a move*/     \
718     static ReturnType InvokedAfterMove(                                        \
719         TypeErasedState*, ForwardedParameterType<P>...) noexcept(noex) {       \
720       ABSL_HARDENING_ASSERT(false && "AnyInvocable use-after-move");           \
721       std::terminate();                                                        \
722     }                                                                          \
723                                                                                \
724     InvokerType<noex, ReturnType, P...>* ExtractInvoker() cv {                 \
725       using QualifiedTestType = int cv ref;                                    \
726       auto* invoker = this->invoker_;                                          \
727       if (!std::is_const<QualifiedTestType>::value &&                          \
728           std::is_rvalue_reference<QualifiedTestType>::value) {                \
729         ABSL_ASSERT([this]() {                                                 \
730           /* We checked that this isn't const above, so const_cast is safe */  \
731           const_cast<Impl*>(this)->invoker_ = InvokedAfterMove;                \
732           return this->HasValue();                                             \
733         }());                                                                  \
734       }                                                                        \
735       return invoker;                                                          \
736     }                                                                          \
737                                                                                \
738     /*The actual invocation operation with the proper signature*/              \
739     ReturnType operator()(P... args) cv ref noexcept(noex) {                   \
740       assert(this->invoker_ != nullptr);                                       \
741       return this->ExtractInvoker()(                                           \
742           const_cast<TypeErasedState*>(&this->state_),                         \
743           static_cast<ForwardedParameterType<P>>(args)...);                    \
744     }                                                                          \
745   }
746 
747 // A convenience macro that defines specializations for the noexcept(true) and
748 // noexcept(false) forms, given the other properties.
749 #define ABSL_INTERNAL_ANY_INVOCABLE_IMPL(cv, ref, inv_quals)    \
750   ABSL_INTERNAL_ANY_INVOCABLE_IMPL_(cv, ref, inv_quals, false); \
751   ABSL_INTERNAL_ANY_INVOCABLE_IMPL_(cv, ref, inv_quals, true)
752 
753 // Non-ref-qualified partial specializations
754 ABSL_INTERNAL_ANY_INVOCABLE_IMPL(, , &);
755 ABSL_INTERNAL_ANY_INVOCABLE_IMPL(const, , const&);
756 
757 // Lvalue-ref-qualified partial specializations
758 ABSL_INTERNAL_ANY_INVOCABLE_IMPL(, &, &);
759 ABSL_INTERNAL_ANY_INVOCABLE_IMPL(const, &, const&);
760 
761 // Rvalue-ref-qualified partial specializations
762 ABSL_INTERNAL_ANY_INVOCABLE_IMPL(, &&, &&);
763 ABSL_INTERNAL_ANY_INVOCABLE_IMPL(const, &&, const&&);
764 
765 // Undef the detail-only macros.
766 #undef ABSL_INTERNAL_ANY_INVOCABLE_IMPL
767 #undef ABSL_INTERNAL_ANY_INVOCABLE_IMPL_
768 #undef ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_false
769 #undef ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_true
770 
771 }  // namespace internal_any_invocable
772 ABSL_NAMESPACE_END
773 }  // namespace absl
774 
775 #endif  // ABSL_FUNCTIONAL_INTERNAL_ANY_INVOCABLE_H_
776