[libcxx-commits] [libcxx] a79a6ea - [libc++][regex] Uses operator<=> in sub_match.

Mark de Wever via libcxx-commits libcxx-commits at lists.llvm.org
Sat Apr 22 03:40:05 PDT 2023


Author: Mark de Wever
Date: 2023-04-22T12:39:19+02:00
New Revision: a79a6ea4a831facc564a36911d79d4472ad93cec

URL: https://github.com/llvm/llvm-project/commit/a79a6ea4a831facc564a36911d79d4472ad93cec
DIFF: https://github.com/llvm/llvm-project/commit/a79a6ea4a831facc564a36911d79d4472ad93cec.diff

LOG: [libc++][regex] Uses operator<=> in sub_match.

The removal of operator!= in this header will be done in a separate
commit.

Note in the synopsis of P1614R2 there is a constexpr
  template<class BiIter>
    constexpr auto operator<=>(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs);

In the implementation of P1614R2 there isn't a constexpr
  template<class BiIter>
    auto operator<=>(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs);

There doesn't seem to be an LWG-issue, but it was fixed in the Standard
by removing the constexpr in b050fd474f11441942c88ef69b8622c8036656ac.

Implements part of:
- P1614R2 The Mothership has Landed

Reviewed By: #libc, ldionne

Differential Revision: https://reviews.llvm.org/D132310

Added: 
    

Modified: 
    libcxx/docs/Status/SpaceshipProjects.csv
    libcxx/include/regex
    libcxx/test/std/re/re.submatch/re.submatch.op/compare.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/Status/SpaceshipProjects.csv b/libcxx/docs/Status/SpaceshipProjects.csv
index 02eac2655d24c..e8624cb6a6724 100644
--- a/libcxx/docs/Status/SpaceshipProjects.csv
+++ b/libcxx/docs/Status/SpaceshipProjects.csv
@@ -77,5 +77,5 @@ Section,Description,Dependencies,Assignee,Complete
 | `[fs.filesystem.syn] <https://wg21.link/fs.filesystem.syn>`_,| `filesystem::space_info <https://reviews.llvm.org/D130861>`_,None,Adrian Vogelsgesang,|Complete|
 | `[fs.path.nonmember] <https://wg21.link/fs.path.nonmember>`_,| `filesystem::path <https://reviews.llvm.org/D130859>`_,None,Adrian Vogelsgesang,|Complete|
 | `[fs.dir.entry.obs] <https://wg21.link/fs.dir.entry.obs>`_,| `filesystem::directory_entry <https://reviews.llvm.org/D130860>`_,None,Adrian Vogelsgesang,|Complete|
-| `[re.submatch.op] <https://wg21.link/re.submatch.op>`_,| `sub_match <https://reviews.llvm.org/D132310>`_,None,Mark de Wever,|In Progress|
+| `[re.submatch.op] <https://wg21.link/re.submatch.op>`_,| `sub_match <https://reviews.llvm.org/D132310>`_,None,Mark de Wever,|Complete|
 | `[thread.thread.id] <https://wg21.link/thread.thread.id>`_,| `thread::id <https://reviews.llvm.org/D131362>`_,None,Adrian Vogelsgesang,|Complete|

diff  --git a/libcxx/include/regex b/libcxx/include/regex
index eae4135ff1b9b..f3d2450d7882d 100644
--- a/libcxx/include/regex
+++ b/libcxx/include/regex
@@ -13,6 +13,7 @@
 /*
     regex synopsis
 
+#include <compare>
 #include <initializer_list>
 
 namespace std
@@ -239,50 +240,54 @@ template <class BiIter>
     operator==(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs);
 
 template <class BiIter>
+    auto
+    operator<=>(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs); // Since C++20
+
+ template <class BiIter>                                                     // Removed in C++20
     bool
     operator!=(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs);
 
-template <class BiIter>
+template <class BiIter>                                                      // Removed in C++20
     bool
     operator<(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs);
 
-template <class BiIter>
+template <class BiIter>                                                      // Removed in C++20
     bool
     operator<=(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs);
 
-template <class BiIter>
+template <class BiIter>                                                      // Removed in C++20
     bool
     operator>=(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs);
 
-template <class BiIter>
+template <class BiIter>                                                      // Removed in C++20
     bool
     operator>(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs);
 
-template <class BiIter, class ST, class SA>
+template <class BiIter, class ST, class SA>                                  // Removed in C++20
     bool
     operator==(const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& lhs,
                const sub_match<BiIter>& rhs);
 
-template <class BiIter, class ST, class SA>
+template <class BiIter, class ST, class SA>                                  // Removed in C++20
     bool
     operator!=(const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& lhs,
                const sub_match<BiIter>& rhs);
 
-template <class BiIter, class ST, class SA>
+template <class BiIter, class ST, class SA>                                  // Removed in C++20
     bool
     operator<(const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& lhs,
               const sub_match<BiIter>& rhs);
 
-template <class BiIter, class ST, class SA>
+template <class BiIter, class ST, class SA>                                  // Removed in C++20
     bool
     operator>(const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& lhs,
               const sub_match<BiIter>& rhs);
 
-template <class BiIter, class ST, class SA>
+template <class BiIter, class ST, class SA>                                  // Removed in C++20
     bool operator>=(const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& lhs,
                     const sub_match<BiIter>& rhs);
 
-template <class BiIter, class ST, class SA>
+template <class BiIter, class ST, class SA>                                  // Removed in C++20
     bool
     operator<=(const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& lhs,
                const sub_match<BiIter>& rhs);
@@ -292,56 +297,62 @@ template <class BiIter, class ST, class SA>
     operator==(const sub_match<BiIter>& lhs,
                const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& rhs);
 
-template <class BiIter, class ST, class SA>
+template <class BiIter, class ST, class SA>                                  // Since C++20
+    auto
+    operator<=>(const sub_match<BiIter>& lhs,
+                const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& rhs);
+
+template <class BiIter, class ST, class SA>                                  // Removed in C++20
     bool
     operator!=(const sub_match<BiIter>& lhs,
                const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& rhs);
 
-template <class BiIter, class ST, class SA>
+template <class BiIter, class ST, class SA>                                  // Removed in C++20
     bool
     operator<(const sub_match<BiIter>& lhs,
               const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& rhs);
 
-template <class BiIter, class ST, class SA>
-    bool operator>(const sub_match<BiIter>& lhs,
+template <class BiIter, class ST, class SA>                                  // Removed in C++20
+    bool
+    operator>(const sub_match<BiIter>& lhs,
                    const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& rhs);
 
-template <class BiIter, class ST, class SA>
+template <class BiIter, class ST, class SA>                                  // Removed in C++20
     bool
     operator>=(const sub_match<BiIter>& lhs,
                const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& rhs);
 
-template <class BiIter, class ST, class SA>
+template <class BiIter, class ST, class SA>                                  // Removed in C++20
     bool
     operator<=(const sub_match<BiIter>& lhs,
                const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& rhs);
 
-template <class BiIter>
+template <class BiIter>                                                      // Removed in C++20
     bool
     operator==(typename iterator_traits<BiIter>::value_type const* lhs,
                const sub_match<BiIter>& rhs);
 
-template <class BiIter>
+template <class BiIter>                                                      // Removed in C++20
     bool
     operator!=(typename iterator_traits<BiIter>::value_type const* lhs,
                const sub_match<BiIter>& rhs);
 
-template <class BiIter>
+template <class BiIter>                                                      // Removed in C++20
     bool
     operator<(typename iterator_traits<BiIter>::value_type const* lhs,
               const sub_match<BiIter>& rhs);
 
-template <class BiIter>
+template <class BiIter>                                                      // Removed in C++20
     bool
     operator>(typename iterator_traits<BiIter>::value_type const* lhs,
               const sub_match<BiIter>& rhs);
 
-template <class BiIter>
+template <class BiIter>                                                      // Removed in C++20
     bool
     operator>=(typename iterator_traits<BiIter>::value_type const* lhs,
                const sub_match<BiIter>& rhs);
 
-template <class BiIter>
+template <class BiIter>                                                      // Removed in C++20
     bool
     operator<=(typename iterator_traits<BiIter>::value_type const* lhs,
                const sub_match<BiIter>& rhs);
@@ -351,57 +362,62 @@ template <class BiIter>
     operator==(const sub_match<BiIter>& lhs,
                typename iterator_traits<BiIter>::value_type const* rhs);
 
-template <class BiIter>
+template <class BiIter>                                                      // Since C++20
+    auto
+    operator<=>(const sub_match<BiIter>& lhs,
+                typename iterator_traits<BiIter>::value_type const* rhs);
+
+template <class BiIter, class ST, class SA>                                  // Removed in C++20
     bool
     operator!=(const sub_match<BiIter>& lhs,
                typename iterator_traits<BiIter>::value_type const* rhs);
 
-template <class BiIter>
+template <class BiIter>                                                      // Removed in C++20
     bool
     operator<(const sub_match<BiIter>& lhs,
               typename iterator_traits<BiIter>::value_type const* rhs);
 
-template <class BiIter>
+template <class BiIter>                                                      // Removed in C++20
     bool
     operator>(const sub_match<BiIter>& lhs,
               typename iterator_traits<BiIter>::value_type const* rhs);
 
-template <class BiIter>
+template <class BiIter>                                                      // Removed in C++20
     bool
     operator>=(const sub_match<BiIter>& lhs,
                typename iterator_traits<BiIter>::value_type const* rhs);
 
-template <class BiIter>
+template <class BiIter>                                                      // Removed in C++20
     bool
     operator<=(const sub_match<BiIter>& lhs,
                typename iterator_traits<BiIter>::value_type const* rhs);
 
-template <class BiIter>
+template <class BiIter>                                                      // Removed in C++20
     bool
     operator==(typename iterator_traits<BiIter>::value_type const& lhs,
                const sub_match<BiIter>& rhs);
 
-template <class BiIter>
+template <class BiIter>                                                      // Removed in C++20
     bool
     operator!=(typename iterator_traits<BiIter>::value_type const& lhs,
                const sub_match<BiIter>& rhs);
 
-template <class BiIter>
+template <class BiIter>                                                      // Removed in C++20
     bool
     operator<(typename iterator_traits<BiIter>::value_type const& lhs,
               const sub_match<BiIter>& rhs);
 
-template <class BiIter>
+template <class BiIter>                                                      // Removed in C++20
     bool
     operator>(typename iterator_traits<BiIter>::value_type const& lhs,
               const sub_match<BiIter>& rhs);
 
-template <class BiIter>
+template <class BiIter>                                                      // Removed in C++20
     bool
     operator>=(typename iterator_traits<BiIter>::value_type const& lhs,
                const sub_match<BiIter>& rhs);
 
-template <class BiIter>
+template <class BiIter>                                                      // Removed in C++20
     bool
     operator<=(typename iterator_traits<BiIter>::value_type const& lhs,
                const sub_match<BiIter>& rhs);
@@ -411,27 +427,32 @@ template <class BiIter>
     operator==(const sub_match<BiIter>& lhs,
                typename iterator_traits<BiIter>::value_type const& rhs);
 
-template <class BiIter>
+template <class BiIter>                                                      // Since C++20
+    auto
+    operator<=>(const sub_match<BiIter>& lhs,
+                typename iterator_traits<BiIter>::value_type const& rhs);
+
+template <class BiIter>                                                      // Removed in C++20
     bool
     operator!=(const sub_match<BiIter>& lhs,
                typename iterator_traits<BiIter>::value_type const& rhs);
 
-template <class BiIter>
+template <class BiIter>                                                      // Removed in C++20
     bool
     operator<(const sub_match<BiIter>& lhs,
               typename iterator_traits<BiIter>::value_type const& rhs);
 
-template <class BiIter>
+template <class BiIter>                                                      // Removed in C++20
     bool
     operator>(const sub_match<BiIter>& lhs,
               typename iterator_traits<BiIter>::value_type const& rhs);
 
-template <class BiIter>
+template <class BiIter>                                                      // Removed in C++20
     bool
     operator>=(const sub_match<BiIter>& lhs,
                typename iterator_traits<BiIter>::value_type const& rhs);
 
-template <class BiIter>
+template <class BiIter>                                                      // Removed in C++20
     bool
     operator<=(const sub_match<BiIter>& lhs,
                typename iterator_traits<BiIter>::value_type const& rhs);
@@ -5032,6 +5053,15 @@ operator==(const sub_match<_BiIter>& __x, const sub_match<_BiIter>& __y)
     return __x.compare(__y) == 0;
 }
 
+#if _LIBCPP_STD_VER >= 20
+template<class _BiIter>
+using __sub_match_cat = compare_three_way_result_t<basic_string<typename iterator_traits<_BiIter>::value_type>>;
+
+template <class _BiIter>
+_LIBCPP_HIDE_FROM_ABI auto operator<=>(const sub_match<_BiIter>& __x, const sub_match<_BiIter>& __y) {
+    return static_cast<__sub_match_cat<_BiIter>>(__x.compare(__y) <=> 0);
+}
+#else // _LIBCPP_STD_VER >= 20
 template <class _BiIter>
 inline _LIBCPP_INLINE_VISIBILITY
 bool
@@ -5124,6 +5154,7 @@ operator<=(const basic_string<typename iterator_traits<_BiIter>::value_type, _ST
 {
     return !(__y < __x);
 }
+#endif // _LIBCPP_STD_VER >= 20
 
 template <class _BiIter, class _ST, class _SA>
 inline _LIBCPP_INLINE_VISIBILITY
@@ -5134,6 +5165,14 @@ operator==(const sub_match<_BiIter>& __x,
     return __x.compare(typename sub_match<_BiIter>::string_type(__y.data(), __y.size())) == 0;
 }
 
+#if _LIBCPP_STD_VER >= 20
+template <class _BiIter, class _ST, class _SA>
+_LIBCPP_HIDE_FROM_ABI auto operator<=>(
+    const sub_match<_BiIter>& __x, const basic_string<typename iterator_traits<_BiIter>::value_type, _ST, _SA>& __y) {
+    return static_cast<__sub_match_cat<_BiIter>>(
+        __x.compare(typename sub_match<_BiIter>::string_type(__y.data(), __y.size())) <=> 0);
+}
+#else // _LIBCPP_STD_VER >= 20
 template <class _BiIter, class _ST, class _SA>
 inline _LIBCPP_INLINE_VISIBILITY
 bool
@@ -5231,6 +5270,7 @@ operator<=(typename iterator_traits<_BiIter>::value_type const* __x,
 {
     return !(__y < __x);
 }
+#endif // _LIBCPP_STD_VER >= 20
 
 template <class _BiIter>
 inline _LIBCPP_INLINE_VISIBILITY
@@ -5241,6 +5281,13 @@ operator==(const sub_match<_BiIter>& __x,
     return __x.compare(__y) == 0;
 }
 
+#if _LIBCPP_STD_VER >= 20
+template <class _BiIter>
+_LIBCPP_HIDE_FROM_ABI auto
+operator<=>(const sub_match<_BiIter>& __x, typename iterator_traits<_BiIter>::value_type const* __y) {
+    return static_cast<__sub_match_cat<_BiIter>>(__x.compare(__y) <=> 0);
+}
+#else // _LIBCPP_STD_VER >= 20
 template <class _BiIter>
 inline _LIBCPP_INLINE_VISIBILITY
 bool
@@ -5341,6 +5388,7 @@ operator<=(typename iterator_traits<_BiIter>::value_type const& __x,
 {
     return !(__y < __x);
 }
+#endif // _LIBCPP_STD_VER >= 20
 
 template <class _BiIter>
 inline _LIBCPP_INLINE_VISIBILITY
@@ -5352,6 +5400,14 @@ operator==(const sub_match<_BiIter>& __x,
     return __x.compare(string_type(1, __y)) == 0;
 }
 
+#if _LIBCPP_STD_VER >= 20
+template <class _BiIter>
+_LIBCPP_HIDE_FROM_ABI auto
+operator<=>(const sub_match<_BiIter>& __x, typename iterator_traits<_BiIter>::value_type const& __y) {
+    using string_type = basic_string<typename iterator_traits<_BiIter>::value_type>;
+    return static_cast<__sub_match_cat<_BiIter>>(__x.compare(string_type(1, __y)) <=> 0);
+}
+#else // _LIBCPP_STD_VER >= 20
 template <class _BiIter>
 inline _LIBCPP_INLINE_VISIBILITY
 bool
@@ -5397,6 +5453,7 @@ operator<=(const sub_match<_BiIter>& __x,
 {
     return !(__y < __x);
 }
+#endif // _LIBCPP_STD_VER >= 20
 
 template <class _CharT, class _ST, class _BiIter>
 inline _LIBCPP_INLINE_VISIBILITY

diff  --git a/libcxx/test/std/re/re.submatch/re.submatch.op/compare.pass.cpp b/libcxx/test/std/re/re.submatch/re.submatch.op/compare.pass.cpp
index be072b1b8b307..6e51825185d88 100644
--- a/libcxx/test/std/re/re.submatch/re.submatch.op/compare.pass.cpp
+++ b/libcxx/test/std/re/re.submatch/re.submatch.op/compare.pass.cpp
@@ -10,6 +10,9 @@
 
 // template <class BidirectionalIterator> class sub_match;
 
+// Note in C++20 several of these operators have been removed and implicitly
+// generated by the compiler using operator== and operator<=>.
+
 // template <class BiIter>
 //     bool
 //     operator==(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs);
@@ -212,16 +215,50 @@
 //     operator<=(const sub_match<BiIter>& lhs,
 //                typename iterator_traits<BiIter>::value_type const& rhs);
 
+// Added in C++20
+// template <class BiIter>
+//     auto
+//     operator<=>(const sub_match<BiIter>& lhs, const sub_match<BiIter>& rhs);
+// template <class BiIter, class ST, class SA>
+//     auto
+//     operator<=>(const sub_match<BiIter>& lhs,
+//                 const basic_string<typename iterator_traits<BiIter>::value_type, ST, SA>& rhs);
+//
+// template <class BiIter>
+//     auto
+//     operator<=>(const sub_match<BiIter>& lhs,
+//                 typename iterator_traits<BiIter>::value_type const* rhs);
+//
+// template <class BiIter>
+//     auto
+//     operator<=>(const sub_match<BiIter>& lhs,
+//                 typename iterator_traits<BiIter>::value_type const& rhs);
+
 #include <regex>
+#include <array>
 #include <cassert>
+
+#include "constexpr_char_traits.h"
+#include "make_string.h"
+#include "test_comparisons.h"
 #include "test_macros.h"
 
+
+#define SV(S) MAKE_STRING_VIEW(CharT, S)
+
 template <class CharT>
 void
 test(const std::basic_string<CharT>& x, const std::basic_string<CharT>& y, bool doCStrTests = true)
 {
     typedef std::basic_string<CharT> string;
     typedef std::sub_match<typename string::const_iterator> sub_match;
+#if TEST_STD_VER > 17
+    AssertOrderReturn<std::strong_ordering, sub_match>();
+    AssertOrderReturn<std::strong_ordering, sub_match, string>();
+#else
+    AssertComparisonsReturnBool<sub_match>();
+    AssertComparisonsReturnBool<sub_match, string>();
+#endif
     sub_match sm1;
     sm1.first = x.begin();
     sm1.second = x.end();
@@ -230,62 +267,95 @@ test(const std::basic_string<CharT>& x, const std::basic_string<CharT>& y, bool
     sm2.first = y.begin();
     sm2.second = y.end();
     sm2.matched = true;
-    assert((sm1 == sm2) == (x == y));
-    assert((sm1 != sm2) == (x != y));
-    assert((sm1 < sm2) == (x < y));
-    assert((sm1 > sm2) == (x > y));
-    assert((sm1 <= sm2) == (x <= y));
-    assert((sm1 >= sm2) == (x >= y));
-    assert((x == sm2) == (x == y));
-    assert((x != sm2) == (x != y));
-    assert((x < sm2) == (x < y));
-    assert((x > sm2) == (x > y));
-    assert((x <= sm2) == (x <= y));
-    assert((x >= sm2) == (x >= y));
-    assert((sm1 == y) == (x == y));
-    assert((sm1 != y) == (x != y));
-    assert((sm1 < y) == (x < y));
-    assert((sm1 > y) == (x > y));
-    assert((sm1 <= y) == (x <= y));
-    assert((sm1 >= y) == (x >= y));
+
+    assert(testComparisons(sm1, sm2, x == y, x < y));
+    assert(testComparisons(x, sm2, x == y, x < y));
+    assert(testComparisons(sm1, y, x == y, x < y));
+#if TEST_STD_VER > 17
+    assert(testOrder(sm1, sm2, x <=> y));
+    assert(testOrder(x, sm2, x <=> y));
+    assert(testOrder(sm1, y, x <=> y));
+#endif
+
     if (doCStrTests) {
-        assert((x.c_str() == sm2) == (x == y));
-        assert((x.c_str() != sm2) == (x != y));
-        assert((x.c_str() < sm2) == (x < y));
-        assert((x.c_str() > sm2) == (x > y));
-        assert((x.c_str() <= sm2) == (x <= y));
-        assert((x.c_str() >= sm2) == (x >= y));
-        assert((sm1 == y.c_str()) == (x == y));
-        assert((sm1 != y.c_str()) == (x != y));
-        assert((sm1 < y.c_str()) == (x < y));
-        assert((sm1 > y.c_str()) == (x > y));
-        assert((sm1 <= y.c_str()) == (x <= y));
-        assert((sm1 >= y.c_str()) == (x >= y));
-        }
-    assert((x[0] == sm2) == (string(1, x[0]) == y));
-    assert((x[0] != sm2) == (string(1, x[0]) != y));
-    assert((x[0] < sm2) == (string(1, x[0]) < y));
-    assert((x[0] > sm2) == (string(1, x[0]) > y));
-    assert((x[0] <= sm2) == (string(1, x[0]) <= y));
-    assert((x[0] >= sm2) == (string(1, x[0]) >= y));
-    assert((sm1 == y[0]) == (x == string(1, y[0])));
-    assert((sm1 != y[0]) == (x != string(1, y[0])));
-    assert((sm1 < y[0]) == (x < string(1, y[0])));
-    assert((sm1 > y[0]) == (x > string(1, y[0])));
-    assert((sm1 <= y[0]) == (x <= string(1, y[0])));
-    assert((sm1 >= y[0]) == (x >= string(1, y[0])));
+        assert(testComparisons(x.c_str(), sm2, x == y, x < y));
+        assert(testComparisons(sm1, y.c_str(), x == y, x < y));
+#if TEST_STD_VER > 17
+        assert(testOrder(x.c_str(), sm2, x <=> y));
+        assert(testOrder(sm1, y.c_str(), x <=> y));
+#endif
+    }
+
+    assert(testComparisons(x[0], sm2, string(1, x[0]) == y, string(1, x[0]) < y));
+    assert(testComparisons(sm1, y[0], x == string(1, y[0]), x < string(1, y[0])));
+#if TEST_STD_VER > 17
+    assert(testOrder(x[0], sm2, (string(1, x[0]) <=> y)));
+    assert(testOrder(sm1, y[0], x <=> (string(1, y[0]))));
+#endif
+}
+
+#if TEST_STD_VER > 17
+template <class CharT, class Ordering>
+struct char_traits : public constexpr_char_traits<CharT> {
+    using comparison_category = Ordering;
+};
+
+template <class T, class Ordering = std::strong_ordering>
+constexpr void test() {
+  AssertOrderAreNoexcept<T>();
+  AssertOrderReturn<Ordering, T>();
+
+  using CharT = typename T::value_type;
+
+  // sorted values
+  std::array s = [] {
+    std::array input{SV(""), SV("abc"), SV("abcdef")};
+    return std::array{
+        T{input[0].begin(), input[0].end()}, T{input[1].begin(), input[1].end()}, T{input[2].begin(), input[2].end()}};
+  }();
+  auto ctor = [](const T& string) {
+    std::sub_match<typename T::const_iterator> sm;
+    sm.first   = string.begin();
+    sm.second  = string.end();
+    sm.matched = true;
+    return sm;
+  };
+  std::array sm{ctor(s[0]), ctor(s[1]), ctor(s[2])};
+
+  for (std::size_t i = 0; i < s.size(); ++i) {
+    for (std::size_t j = 0; j < s.size(); ++j) {
+      assert(testOrder(s[i], sm[j], i == j ? Ordering::equivalent : i < j ? Ordering::less : Ordering::greater));
+    }
+  }
 }
 
+template <class CharT>
+constexpr void test_all_orderings() {
+  test<std::basic_string<CharT>>(); // Strong ordering in its char_traits
+  test<std::basic_string<CharT, constexpr_char_traits<CharT>>,
+       std::weak_ordering>(); // No ordering in its char_traits
+  test<std::basic_string<CharT, char_traits<CharT, std::weak_ordering>>, std::weak_ordering>();
+  test<std::basic_string<CharT, char_traits<CharT, std::partial_ordering>>, std::partial_ordering>();
+}
+#endif //  TEST_STD_VER > 17
+
 int main(int, char**)
 {
     test(std::string("123"), std::string("123"));
     test(std::string("1234"), std::string("123"));
     test(std::string("123\000" "56", 6), std::string("123\000" "56", 6), false);
+#if TEST_STD_VER > 17
+    test_all_orderings<char>();
+#endif
+
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
     test(std::wstring(L"123"), std::wstring(L"123"));
     test(std::wstring(L"1234"), std::wstring(L"123"));
     test(std::wstring(L"123\000" L"56", 6), std::wstring(L"123\000" L"56", 6), false);
+#if TEST_STD_VER > 17
+    test_all_orderings<wchar_t>();
 #endif
+#endif // TEST_HAS_NO_WIDE_CHARACTERS
 
   return 0;
 }


        


More information about the libcxx-commits mailing list