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 @@ ...@@ -22,6 +22,7 @@
#include <type_traits> #include <type_traits>
#include "absl/algorithm/algorithm.h" #include "absl/algorithm/algorithm.h"
#include "absl/base/config.h"
#include "absl/base/internal/throw_delegate.h" #include "absl/base/internal/throw_delegate.h"
#include "absl/meta/type_traits.h" #include "absl/meta/type_traits.h"
...@@ -86,13 +87,13 @@ using EnableIfMutable = ...@@ -86,13 +87,13 @@ using EnableIfMutable =
typename std::enable_if<!std::is_const<T>::value, int>::type; typename std::enable_if<!std::is_const<T>::value, int>::type;
template <template <typename> class SpanT, typename T> 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, ""); static_assert(std::is_const<T>::value, "");
return std::equal(a.begin(), a.end(), b.begin(), b.end()); return std::equal(a.begin(), a.end(), b.begin(), b.end());
} }
template <template <typename> class SpanT, typename T> 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 // We can't use value_type since that is remove_cv_t<T>, so we go the long way
// around. // around.
static_assert(std::is_const<T>::value, ""); static_assert(std::is_const<T>::value, "");
......
...@@ -522,157 +522,165 @@ const typename Span<T>::size_type Span<T>::npos; ...@@ -522,157 +522,165 @@ const typename Span<T>::size_type Span<T>::npos;
// operator== // operator==
template <typename T> 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); return span_internal::EqualImpl<Span, const T>(a, b);
} }
template <typename T> 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); return span_internal::EqualImpl<Span, const T>(a, b);
} }
template <typename T> 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); return span_internal::EqualImpl<Span, const T>(a, b);
} }
template < template <
typename T, typename U, typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> 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); return span_internal::EqualImpl<Span, const T>(a, b);
} }
template < template <
typename T, typename U, typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> 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); return span_internal::EqualImpl<Span, const T>(a, b);
} }
// operator!= // operator!=
template <typename T> 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); return !(a == b);
} }
template <typename T> 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); return !(a == b);
} }
template <typename T> 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); return !(a == b);
} }
template < template <
typename T, typename U, typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> 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); return !(a == b);
} }
template < template <
typename T, typename U, typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> 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); return !(a == b);
} }
// operator< // operator<
template <typename T> 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); return span_internal::LessThanImpl<Span, const T>(a, b);
} }
template <typename T> 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); return span_internal::LessThanImpl<Span, const T>(a, b);
} }
template <typename T> 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); return span_internal::LessThanImpl<Span, const T>(a, b);
} }
template < template <
typename T, typename U, typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> 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); return span_internal::LessThanImpl<Span, const T>(a, b);
} }
template < template <
typename T, typename U, typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> 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); return span_internal::LessThanImpl<Span, const T>(a, b);
} }
// operator> // operator>
template <typename T> 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; return b < a;
} }
template <typename T> 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; return b < a;
} }
template <typename T> 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; return b < a;
} }
template < template <
typename T, typename U, typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> 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; return b < a;
} }
template < template <
typename T, typename U, typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> 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; return b < a;
} }
// operator<= // operator<=
template <typename T> 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); return !(b < a);
} }
template <typename T> 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); return !(b < a);
} }
template <typename T> 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); return !(b < a);
} }
template < template <
typename T, typename U, typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> 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); return !(b < a);
} }
template < template <
typename T, typename U, typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> 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); return !(b < a);
} }
// operator>= // operator>=
template <typename T> 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); return !(a < b);
} }
template <typename T> 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); return !(a < b);
} }
template <typename T> 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); return !(a < b);
} }
template < template <
typename T, typename U, typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> 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); return !(a < b);
} }
template < template <
typename T, typename U, typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>> 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); return !(a < b);
} }
......
...@@ -787,9 +787,9 @@ TEST(IntSpan, NoexceptTest) { ...@@ -787,9 +787,9 @@ TEST(IntSpan, NoexceptTest) {
template <int i> template <int i>
struct ConstexprTester {}; struct ConstexprTester {};
#define ABSL_TEST_CONSTEXPR(expr) \ #define ABSL_TEST_CONSTEXPR(expr) \
do { \ do { \
ABSL_ATTRIBUTE_UNUSED ConstexprTester<(expr, 1)> t; \ ABSL_ATTRIBUTE_UNUSED ConstexprTester<(static_cast<void>(expr), 1)> t; \
} while (0) } while (0)
struct ContainerWithConstexprMethods { struct ContainerWithConstexprMethods {
...@@ -826,6 +826,41 @@ TEST(ConstIntSpan, ConstexprTest) { ...@@ -826,6 +826,41 @@ TEST(ConstIntSpan, ConstexprTest) {
ABSL_TEST_CONSTEXPR(span[0]); 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 { struct BigStruct {
char bytes[10000]; 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