diff --git a/libcxx/include/__chrono/day.h b/libcxx/include/__chrono/day.h --- a/libcxx/include/__chrono/day.h +++ b/libcxx/include/__chrono/day.h @@ -12,6 +12,7 @@ #include <__chrono/duration.h> #include <__config> +#include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header @@ -45,25 +46,9 @@ bool operator==(const day& __lhs, const day& __rhs) noexcept { return static_cast(__lhs) == static_cast(__rhs); } -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator!=(const day& __lhs, const day& __rhs) noexcept -{ return !(__lhs == __rhs); } - -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator< (const day& __lhs, const day& __rhs) noexcept -{ return static_cast(__lhs) < static_cast(__rhs); } - -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator> (const day& __lhs, const day& __rhs) noexcept -{ return __rhs < __lhs; } - -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator<=(const day& __lhs, const day& __rhs) noexcept -{ return !(__rhs < __lhs);} - -_LIBCPP_HIDE_FROM_ABI inline constexpr -bool operator>=(const day& __lhs, const day& __rhs) noexcept -{ return !(__lhs < __rhs); } +_LIBCPP_HIDE_FROM_ABI constexpr +strong_ordering operator<=>(const day& __lhs, const day& __rhs) noexcept +{ return static_cast(__lhs) <=> static_cast(__rhs); } _LIBCPP_HIDE_FROM_ABI inline constexpr day operator+ (const day& __lhs, const days& __rhs) noexcept diff --git a/libcxx/include/chrono b/libcxx/include/chrono --- a/libcxx/include/chrono +++ b/libcxx/include/chrono @@ -13,6 +13,8 @@ /* chrono synopsis +#include // C++20 + namespace std { namespace chrono @@ -325,11 +327,7 @@ class day; constexpr bool operator==(const day& x, const day& y) noexcept; -constexpr bool operator!=(const day& x, const day& y) noexcept; -constexpr bool operator< (const day& x, const day& y) noexcept; -constexpr bool operator> (const day& x, const day& y) noexcept; -constexpr bool operator<=(const day& x, const day& y) noexcept; -constexpr bool operator>=(const day& x, const day& y) noexcept; +constexpr strong_ordering operator<=>(const day& x, const day& y) noexcept; constexpr day operator+(const day& x, const days& y) noexcept; constexpr day operator+(const days& x, const day& y) noexcept; constexpr day operator-(const day& x, const days& y) noexcept; @@ -715,9 +713,11 @@ #include <__chrono/year_month_day.h> #include <__chrono/year_month_weekday.h> #include <__config> -#include #include +// standard-mandated includes +#include + #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # pragma GCC system_header #endif diff --git a/libcxx/test/std/time/time.cal/time.cal.day/time.cal.day.nonmembers/comparisons.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.day/time.cal.day.nonmembers/comparisons.pass.cpp --- a/libcxx/test/std/time/time.cal/time.cal.day/time.cal.day.nonmembers/comparisons.pass.cpp +++ b/libcxx/test/std/time/time.cal/time.cal.day/time.cal.day.nonmembers/comparisons.pass.cpp @@ -12,9 +12,8 @@ // constexpr bool operator==(const day& x, const day& y) noexcept; // Returns: unsigned{x} == unsigned{y}. -// constexpr bool operator<(const day& x, const day& y) noexcept; -// Returns: unsigned{x} < unsigned{y}. - +// constexpr strong_ordering operator<=>(const day& x, const day& y) noexcept; +// Returns: unsigned{x} <=> unsigned{y}. #include #include @@ -23,23 +22,30 @@ #include "test_macros.h" #include "test_comparisons.h" -int main(int, char**) -{ - using day = std::chrono::day; +constexpr bool test() { + using day = std::chrono::day; + + // Validate invalid values. The range [0, 255] is guaranteed to be allowed. + assert(testComparisons6Values(0U, 0U)); + assert(testComparisons6Values(0U, 1U)); + assert(testComparisons6Values(254U, 255U)); + assert(testComparisons6Values(255U, 255U)); - AssertComparisons6AreNoexcept(); - AssertComparisons6ReturnBool(); + // Validate some valid values. + for (unsigned i = 1; i < 10; ++i) + for (unsigned j = 1; j < 10; ++j) + assert(testComparisons6Values(i, j)); - static_assert(testComparisons6Values(0U, 0U), ""); - static_assert(testComparisons6Values(0U, 1U), ""); + return true; +} - // Some 'ok' values as well - static_assert(testComparisons6Values( 5U, 5U), ""); - static_assert(testComparisons6Values( 5U, 10U), ""); +int main(int, char**) { + using day = std::chrono::day; + AssertComparisons7AreNoexcept(); + AssertComparisonsESReturnBoolOrdering(); - for (unsigned i = 1; i < 10; ++i) - for (unsigned j = 1; j < 10; ++j) - assert(testComparisons6Values(i, j)); + test(); + static_assert(test()); return 0; } diff --git a/libcxx/test/support/test_comparisons.h b/libcxx/test/support/test_comparisons.h --- a/libcxx/test/support/test_comparisons.h +++ b/libcxx/test/support/test_comparisons.h @@ -7,12 +7,18 @@ //===----------------------------------------------------------------------===// // A set of routines for testing the comparison operators of a type // -// XXXX6 tests all six comparison operators -// XXXX2 tests only op== and op!= +// XXXX7 tests all seven comparison operators (the seventh is C++20's operator<=>) +// XXXXES tests op== and op<=> where both can have different suffixes. +// XXXX6 tests all six comparison operators +// XXXX2 tests only op== and op!= // -// AssertComparisonsXAreNoexcept static_asserts that the operations are all noexcept. -// AssertComparisonsXReturnBool static_asserts that the operations return bool. -// AssertComparisonsXConvertibleToBool static_asserts that the operations return something convertible to bool. +// AssertComparisonsXAreNoexcept static_asserts that the operations are all noexcept. +// AssertComparisonsXReturnBool static_asserts that the operations return bool. +// AssertComparisonsXConvertibleToBool static_asserts that the operations return something convertible to bool. +// testComparisonsXValues returns the result of the comparison of all operations. +// +// AssertComparisonsESReturnBoolOrdering static_asserts that op== returns bool and the other six opertions return +// the requested Ordering. The Standard library uses this pattern quite often. #ifndef TEST_COMPARISONS_H @@ -97,6 +103,7 @@ ASSERT_NOEXCEPT(std::declval() >= std::declval()); } + template void AssertComparisons6ReturnBool() { @@ -120,6 +127,22 @@ static_assert((std::is_convertible() >= std::declval()), bool>::value), ""); } +#if TEST_STD_VER > 17 +template +void AssertComparisons7AreNoexcept() +{ + AssertComparisons6AreNoexcept(); + ASSERT_NOEXCEPT(std::declval() <=> std::declval()); +} + +template +void AssertComparisonsESReturnBoolOrdering() +{ + ASSERT_SAME_TYPE(decltype(std::declval() == std::declval()), bool); + ASSERT_SAME_TYPE(decltype(std::declval() <=> std::declval()), Ordering); +} +#endif + // Test all two comparison operations for sanity template TEST_CONSTEXPR_CXX14 bool testComparisons2(const T& t1, const U& t2, bool isEqual)