mirror of
https://github.com/abseil/abseil-cpp.git
synced 2026-06-04 12:07:05 +08:00
Make absl::Condition work with C++23 deducing-this
Closes: #1992 PiperOrigin-RevId: 857136106 Change-Id: Iae31d7c6c9a0fda16ebf2c4f68764da521d036bf
This commit is contained in:
committed by
Copybara-Service
parent
eef1a08f4b
commit
28e6a799ba
@@ -61,6 +61,7 @@
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <type_traits>
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/base/config.h"
|
||||
@@ -81,6 +82,18 @@ ABSL_NAMESPACE_BEGIN
|
||||
class Condition;
|
||||
struct SynchWaitParams;
|
||||
|
||||
namespace synchronization_internal {
|
||||
|
||||
template <typename T, typename = void>
|
||||
struct HasConstMemberCallOperator : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
struct HasConstMemberCallOperator<
|
||||
T, std::void_t<decltype(static_cast<bool (T::*)() const>(&T::operator()))>>
|
||||
: std::true_type {};
|
||||
|
||||
} // namespace synchronization_internal
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Mutex
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -866,11 +879,23 @@ class Condition {
|
||||
// Implementation note: The second template parameter ensures that this
|
||||
// constructor doesn't participate in overload resolution if T doesn't have
|
||||
// `bool operator() const`.
|
||||
template <typename T, typename E = decltype(static_cast<bool (T::*)() const>(
|
||||
&T::operator()))>
|
||||
template <typename T,
|
||||
std::enable_if_t<
|
||||
synchronization_internal::HasConstMemberCallOperator<T>::value,
|
||||
int> = 0>
|
||||
explicit Condition(const T* absl_nonnull obj)
|
||||
: Condition(obj, static_cast<bool (T::*)() const>(&T::operator())) {}
|
||||
|
||||
// Constructor for functors that do not match the `bool operator()() const`
|
||||
// signature, such as those using C++23 "deducing this" or static operator().
|
||||
template <
|
||||
typename T,
|
||||
typename = std::enable_if_t<
|
||||
!synchronization_internal::HasConstMemberCallOperator<T>::value &&
|
||||
sizeof(static_cast<bool (*)(const T&)>(&T::operator())) != 0>>
|
||||
explicit Condition(const T* absl_nonnull obj)
|
||||
: Condition(&CallByRef<T>, obj) {}
|
||||
|
||||
// A Condition that always returns `true`.
|
||||
// kTrue is only useful in a narrow set of circumstances, mostly when
|
||||
// it's passed conditionally. For example:
|
||||
@@ -932,6 +957,11 @@ class Condition {
|
||||
template <typename T, typename ConditionMethodPtr>
|
||||
static bool CastAndCallMethod(const Condition* absl_nonnull c);
|
||||
|
||||
template <typename T>
|
||||
static bool CallByRef(const T* absl_nonnull self) {
|
||||
return (*self)();
|
||||
}
|
||||
|
||||
// Helper methods for storing, validating, and reading callback arguments.
|
||||
template <typename T>
|
||||
inline void StoreCallback(T callback) {
|
||||
|
||||
@@ -993,6 +993,20 @@ TEST(Mutex, FunctionPointerConditionWithConstMethod) {
|
||||
EXPECT_TRUE(absl::Condition(&chapman, &Constable::WotsAllThisThen).Eval());
|
||||
}
|
||||
|
||||
#ifdef __cpp_explicit_this_parameter
|
||||
struct TrueViaDeducingThis {
|
||||
template <class This, class... Args>
|
||||
bool operator()(this const This&, Args...) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(Mutex, FunctorConditionDeducingThis) {
|
||||
TrueViaDeducingThis f;
|
||||
EXPECT_TRUE(absl::Condition(&f).Eval());
|
||||
}
|
||||
#endif
|
||||
|
||||
struct True {
|
||||
template <class... Args>
|
||||
bool operator()(Args...) const {
|
||||
|
||||
Reference in New Issue
Block a user