Commit 8d272b28 by Abseil Team Committed by Copybara-Service

Make Span's relational operators constexpr since C++20.

_The implementation has not changed, only constexpr markers have been added._

PiperOrigin-RevId: 695435063
Change-Id: I66cd03195e429534c0e58c330f1019c89025abed
parent feb6aab8
......@@ -22,6 +22,7 @@
#include <type_traits>
#include "absl/algorithm/algorithm.h"
#include "absl/base/config.h"
#include "absl/base/internal/throw_delegate.h"
#include "absl/meta/type_traits.h"
......@@ -86,13 +87,13 @@ using EnableIfMutable =
typename std::enable_if<!std::is_const<T>::value, int>::type;
template <template <typename> class SpanT, typename T>
bool EqualImpl(SpanT<T> a, SpanT<T> b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool EqualImpl(SpanT<T> a, SpanT<T> b) {
static_assert(std::is_const<T>::value, "");
return std::equal(a.begin(), a.end(), b.begin(), b.end());
}
template <template <typename> class SpanT, typename T>
bool LessThanImpl(SpanT<T> a, SpanT<T> b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool LessThanImpl(SpanT<T> a, SpanT<T> b) {
// We can't use value_type since that is remove_cv_t<T>, so we go the long way
// around.
static_assert(std::is_const<T>::value, "");
......
......@@ -522,157 +522,165 @@ const typename Span<T>::size_type Span<T>::npos;
// operator==
template <typename T>
bool operator==(Span<T> a, Span<T> b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator==(Span<T> a, Span<T> b) {
return span_internal::EqualImpl<Span, const T>(a, b);
}
template <typename T>
bool operator==(Span<const T> a, Span<T> b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator==(Span<const T> a,
Span<T> b) {
return span_internal::EqualImpl<Span, const T>(a, b);
}
template <typename T>
bool operator==(Span<T> a, Span<const T> b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator==(Span<T> a,
Span<const T> b) {
return span_internal::EqualImpl<Span, const T>(a, b);
}
template <
typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator==(const U& a, Span<T> b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator==(const U& a, Span<T> b) {
return span_internal::EqualImpl<Span, const T>(a, b);
}
template <
typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator==(Span<T> a, const U& b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator==(Span<T> a, const U& b) {
return span_internal::EqualImpl<Span, const T>(a, b);
}
// operator!=
template <typename T>
bool operator!=(Span<T> a, Span<T> b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator!=(Span<T> a, Span<T> b) {
return !(a == b);
}
template <typename T>
bool operator!=(Span<const T> a, Span<T> b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator!=(Span<const T> a,
Span<T> b) {
return !(a == b);
}
template <typename T>
bool operator!=(Span<T> a, Span<const T> b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator!=(Span<T> a,
Span<const T> b) {
return !(a == b);
}
template <
typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator!=(const U& a, Span<T> b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator!=(const U& a, Span<T> b) {
return !(a == b);
}
template <
typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator!=(Span<T> a, const U& b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator!=(Span<T> a, const U& b) {
return !(a == b);
}
// operator<
template <typename T>
bool operator<(Span<T> a, Span<T> b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<(Span<T> a, Span<T> b) {
return span_internal::LessThanImpl<Span, const T>(a, b);
}
template <typename T>
bool operator<(Span<const T> a, Span<T> b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<(Span<const T> a, Span<T> b) {
return span_internal::LessThanImpl<Span, const T>(a, b);
}
template <typename T>
bool operator<(Span<T> a, Span<const T> b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<(Span<T> a, Span<const T> b) {
return span_internal::LessThanImpl<Span, const T>(a, b);
}
template <
typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator<(const U& a, Span<T> b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<(const U& a, Span<T> b) {
return span_internal::LessThanImpl<Span, const T>(a, b);
}
template <
typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator<(Span<T> a, const U& b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<(Span<T> a, const U& b) {
return span_internal::LessThanImpl<Span, const T>(a, b);
}
// operator>
template <typename T>
bool operator>(Span<T> a, Span<T> b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>(Span<T> a, Span<T> b) {
return b < a;
}
template <typename T>
bool operator>(Span<const T> a, Span<T> b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>(Span<const T> a, Span<T> b) {
return b < a;
}
template <typename T>
bool operator>(Span<T> a, Span<const T> b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>(Span<T> a, Span<const T> b) {
return b < a;
}
template <
typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator>(const U& a, Span<T> b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>(const U& a, Span<T> b) {
return b < a;
}
template <
typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator>(Span<T> a, const U& b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>(Span<T> a, const U& b) {
return b < a;
}
// operator<=
template <typename T>
bool operator<=(Span<T> a, Span<T> b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<=(Span<T> a, Span<T> b) {
return !(b < a);
}
template <typename T>
bool operator<=(Span<const T> a, Span<T> b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<=(Span<const T> a,
Span<T> b) {
return !(b < a);
}
template <typename T>
bool operator<=(Span<T> a, Span<const T> b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<=(Span<T> a,
Span<const T> b) {
return !(b < a);
}
template <
typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator<=(const U& a, Span<T> b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<=(const U& a, Span<T> b) {
return !(b < a);
}
template <
typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator<=(Span<T> a, const U& b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<=(Span<T> a, const U& b) {
return !(b < a);
}
// operator>=
template <typename T>
bool operator>=(Span<T> a, Span<T> b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>=(Span<T> a, Span<T> b) {
return !(a < b);
}
template <typename T>
bool operator>=(Span<const T> a, Span<T> b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>=(Span<const T> a,
Span<T> b) {
return !(a < b);
}
template <typename T>
bool operator>=(Span<T> a, Span<const T> b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>=(Span<T> a,
Span<const T> b) {
return !(a < b);
}
template <
typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator>=(const U& a, Span<T> b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>=(const U& a, Span<T> b) {
return !(a < b);
}
template <
typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator>=(Span<T> a, const U& b) {
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>=(Span<T> a, const U& b) {
return !(a < b);
}
......
......@@ -789,7 +789,7 @@ struct ConstexprTester {};
#define ABSL_TEST_CONSTEXPR(expr) \
do { \
ABSL_ATTRIBUTE_UNUSED ConstexprTester<(expr, 1)> t; \
ABSL_ATTRIBUTE_UNUSED ConstexprTester<(static_cast<void>(expr), 1)> t; \
} while (0)
struct ContainerWithConstexprMethods {
......@@ -826,6 +826,41 @@ TEST(ConstIntSpan, ConstexprTest) {
ABSL_TEST_CONSTEXPR(span[0]);
}
#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
TEST(ConstIntSpan, ConstexprRelOpsTest) {
static constexpr int lhs_data[] = {1, 2, 3};
static constexpr int rhs_data[] = {1, 2, 3};
constexpr absl::Span<const int> lhs = absl::MakeConstSpan(lhs_data, 3);
constexpr absl::Span<const int> rhs = absl::MakeConstSpan(rhs_data, 3);
ABSL_TEST_CONSTEXPR(lhs_data == rhs);
ABSL_TEST_CONSTEXPR(lhs_data != rhs);
ABSL_TEST_CONSTEXPR(lhs_data < rhs);
ABSL_TEST_CONSTEXPR(lhs_data <= rhs);
ABSL_TEST_CONSTEXPR(lhs_data > rhs);
ABSL_TEST_CONSTEXPR(lhs_data >= rhs);
ABSL_TEST_CONSTEXPR(lhs == rhs);
ABSL_TEST_CONSTEXPR(lhs != rhs);
ABSL_TEST_CONSTEXPR(lhs < rhs);
ABSL_TEST_CONSTEXPR(lhs <= rhs);
ABSL_TEST_CONSTEXPR(lhs > rhs);
ABSL_TEST_CONSTEXPR(lhs >= rhs);
ABSL_TEST_CONSTEXPR(lhs == rhs_data);
ABSL_TEST_CONSTEXPR(lhs != rhs_data);
ABSL_TEST_CONSTEXPR(lhs < rhs_data);
ABSL_TEST_CONSTEXPR(lhs <= rhs_data);
ABSL_TEST_CONSTEXPR(lhs > rhs_data);
ABSL_TEST_CONSTEXPR(lhs >= rhs_data);
}
#endif // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) &&
// ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
struct BigStruct {
char bytes[10000];
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment