aboutsummaryrefslogtreecommitdiff
path: root/absl/functional/internal/any_invocable.h
diff options
context:
space:
mode:
Diffstat (limited to 'absl/functional/internal/any_invocable.h')
-rw-r--r--absl/functional/internal/any_invocable.h37
1 files changed, 31 insertions, 6 deletions
diff --git a/absl/functional/internal/any_invocable.h b/absl/functional/internal/any_invocable.h
index 35b389d1..d41b7e56 100644
--- a/absl/functional/internal/any_invocable.h
+++ b/absl/functional/internal/any_invocable.h
@@ -56,6 +56,7 @@
#include <cassert>
#include <cstddef>
#include <cstring>
+#include <exception>
#include <functional>
#include <initializer_list>
#include <memory>
@@ -66,6 +67,7 @@
#include "absl/base/config.h"
#include "absl/base/internal/invoke.h"
#include "absl/base/macros.h"
+#include "absl/base/optimization.h"
#include "absl/meta/type_traits.h"
#include "absl/utility/utility.h"
@@ -281,7 +283,7 @@ void LocalManagerNontrivial(FunctionToCall operation,
from_object.~T(); // Must not throw. // NOLINT
return;
}
- ABSL_INTERNAL_UNREACHABLE;
+ ABSL_UNREACHABLE();
}
// The invoker that is used when a target function is in local storage
@@ -319,7 +321,7 @@ inline void RemoteManagerTrivial(FunctionToCall operation,
#endif // __cpp_sized_deallocation
return;
}
- ABSL_INTERNAL_UNREACHABLE;
+ ABSL_UNREACHABLE();
}
// The manager that is used when a target function is in remote storage and the
@@ -341,7 +343,7 @@ void RemoteManagerNontrivial(FunctionToCall operation,
::delete static_cast<T*>(from->remote.target); // Must not throw.
return;
}
- ABSL_INTERNAL_UNREACHABLE;
+ ABSL_UNREACHABLE();
}
// The invoker that is used when a target function is in remote storage
@@ -486,7 +488,7 @@ class CoreImpl {
// object.
Clear();
- // Perform the actual move/destory operation on the target function.
+ // Perform the actual move/destroy operation on the target function.
other.manager_(FunctionToCall::relocate_from_to, &other.state_, &state_);
manager_ = other.manager_;
invoker_ = other.invoker_;
@@ -809,11 +811,34 @@ using CanAssignReferenceWrapper = TrueAlias<
: Core(absl::in_place_type<absl::decay_t<T> inv_quals>, \
std::forward<Args>(args)...) {} \
\
+ /*Raises a fatal error when the AnyInvocable is invoked after a move*/ \
+ static ReturnType InvokedAfterMove( \
+ TypeErasedState*, \
+ ForwardedParameterType<P>...) noexcept(noex) { \
+ ABSL_HARDENING_ASSERT(false && "AnyInvocable use-after-move"); \
+ std::terminate(); \
+ } \
+ \
+ 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_ASSERT([this]() { \
+ /* We checked that this isn't const above, so const_cast is safe */ \
+ const_cast<Impl*>(this)->invoker_ = InvokedAfterMove; \
+ 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)...); \
} \
}