summaryrefslogtreecommitdiff
path: root/absl/functional/internal/any_invocable.h
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2022-10-11 10:27:17 -0700
committerGravatar Copybara-Service <copybara-worker@google.com>2022-10-11 10:28:00 -0700
commit73789eb0689071b0b02b00cb3daed9f224ff1a10 (patch)
treeb6fec5c27f8d6044655b85b021d5702e5f3b73e8 /absl/functional/internal/any_invocable.h
parent845610e80b66aa3d834f4d1b401133919bf7fadb (diff)
Detects accidental multiple invocations of AnyInvocable<R(...)&&>::operator()&& by producing an error in debug mode, and clarifies that the behavior is undefined in the general case.
PiperOrigin-RevId: 480392976 Change-Id: I2d4c6f213fa7c8747f125c9735272a8e47b9214b
Diffstat (limited to 'absl/functional/internal/any_invocable.h')
-rw-r--r--absl/functional/internal/any_invocable.h24
1 files changed, 22 insertions, 2 deletions
diff --git a/absl/functional/internal/any_invocable.h b/absl/functional/internal/any_invocable.h
index 35b389d1..8fce4bf6 100644
--- a/absl/functional/internal/any_invocable.h
+++ b/absl/functional/internal/any_invocable.h
@@ -809,11 +809,31 @@ using CanAssignReferenceWrapper = TrueAlias<
: Core(absl::in_place_type<absl::decay_t<T> inv_quals>, \
std::forward<Args>(args)...) {} \
\
+ InvokerType<noex, ReturnType, P...>* ExtractInvoker() cv { \
+ using QualifiedTestType = int cv ref; \
+ auto* invoker = this->invoker_; \
+ if (!std::is_const<QualifiedTestType>::value && \
+ std::is_rvalue_reference<QualifiedTestType>::value) { \
+ ABSL_HARDENING_ASSERT([this]() { \
+ /* We checked that this isn't const above, so const_cast is safe */ \
+ const_cast<Impl*>(this)->invoker_ = \
+ [](TypeErasedState*, \
+ ForwardedParameterType<P>...) noexcept(noex) -> ReturnType { \
+ ABSL_HARDENING_ASSERT(false && "AnyInvocable use-after-move"); \
+ std::terminate(); \
+ }; \
+ return this->HasValue(); \
+ }()); \
+ } \
+ return invoker; \
+ } \
+ \
/*The actual invocation operation with the proper signature*/ \
ReturnType operator()(P... args) cv ref noexcept(noex) { \
assert(this->invoker_ != nullptr); \
- return this->invoker_(const_cast<TypeErasedState*>(&this->state_), \
- static_cast<ForwardedParameterType<P>>(args)...); \
+ return this->ExtractInvoker()( \
+ const_cast<TypeErasedState*>(&this->state_), \
+ static_cast<ForwardedParameterType<P>>(args)...); \
} \
}