diff --git a/libcxx/docs/Status/SpaceshipProjects.csv b/libcxx/docs/Status/SpaceshipProjects.csv --- a/libcxx/docs/Status/SpaceshipProjects.csv +++ b/libcxx/docs/Status/SpaceshipProjects.csv @@ -77,5 +77,5 @@ | `[fs.filesystem.syn] `_,| `filesystem::space_info `_,None,Adrian Vogelsgesang,|Complete| | `[fs.path.nonmember] `_,| `filesystem::path `_,None,Adrian Vogelsgesang,|Complete| | `[fs.dir.entry.obs] `_,| `filesystem::directory_entry `_,None,Adrian Vogelsgesang,|Complete| -| `[re.submatch.op] `_,| sub_match,None,Mark de Wever,|In Progress| +| `[re.submatch.op] `_,| sub_match,None,Mark de Wever,|Complete| | `[thread.thread.id] `_,| `thread::id `_,None,Adrian Vogelsgesang,|Complete| diff --git a/libcxx/include/regex b/libcxx/include/regex --- a/libcxx/include/regex +++ b/libcxx/include/regex @@ -13,6 +13,7 @@ /* regex synopsis +#include #include namespace std @@ -237,50 +238,54 @@ operator==(const sub_match& lhs, const sub_match& rhs); template + auto + operator<=>(const sub_match& lhs, const sub_match& rhs); // Since C++20 + + template // Removed in C++20 bool operator!=(const sub_match& lhs, const sub_match& rhs); -template +template // Removed in C++20 bool operator<(const sub_match& lhs, const sub_match& rhs); -template +template // Removed in C++20 bool operator<=(const sub_match& lhs, const sub_match& rhs); -template +template // Removed in C++20 bool operator>=(const sub_match& lhs, const sub_match& rhs); -template +template // Removed in C++20 bool operator>(const sub_match& lhs, const sub_match& rhs); -template +template // Removed in C++20 bool operator==(const basic_string::value_type, ST, SA>& lhs, const sub_match& rhs); -template +template // Removed in C++20 bool operator!=(const basic_string::value_type, ST, SA>& lhs, const sub_match& rhs); -template +template // Removed in C++20 bool operator<(const basic_string::value_type, ST, SA>& lhs, const sub_match& rhs); -template +template // Removed in C++20 bool operator>(const basic_string::value_type, ST, SA>& lhs, const sub_match& rhs); -template +template // Removed in C++20 bool operator>=(const basic_string::value_type, ST, SA>& lhs, const sub_match& rhs); -template +template // Removed in C++20 bool operator<=(const basic_string::value_type, ST, SA>& lhs, const sub_match& rhs); @@ -290,56 +295,62 @@ operator==(const sub_match& lhs, const basic_string::value_type, ST, SA>& rhs); -template +template // Since C++20 + auto + operator<=>(const sub_match& lhs, + const basic_string::value_type, ST, SA>& rhs); + +template // Removed in C++20 bool operator!=(const sub_match& lhs, const basic_string::value_type, ST, SA>& rhs); -template +template // Removed in C++20 bool operator<(const sub_match& lhs, const basic_string::value_type, ST, SA>& rhs); -template - bool operator>(const sub_match& lhs, +template // Removed in C++20 + bool + operator>(const sub_match& lhs, const basic_string::value_type, ST, SA>& rhs); -template +template // Removed in C++20 bool operator>=(const sub_match& lhs, const basic_string::value_type, ST, SA>& rhs); -template +template // Removed in C++20 bool operator<=(const sub_match& lhs, const basic_string::value_type, ST, SA>& rhs); -template +template // Removed in C++20 bool operator==(typename iterator_traits::value_type const* lhs, const sub_match& rhs); -template +template // Removed in C++20 bool operator!=(typename iterator_traits::value_type const* lhs, const sub_match& rhs); -template +template // Removed in C++20 bool operator<(typename iterator_traits::value_type const* lhs, const sub_match& rhs); -template +template // Removed in C++20 bool operator>(typename iterator_traits::value_type const* lhs, const sub_match& rhs); -template +template // Removed in C++20 bool operator>=(typename iterator_traits::value_type const* lhs, const sub_match& rhs); -template +template // Removed in C++20 bool operator<=(typename iterator_traits::value_type const* lhs, const sub_match& rhs); @@ -349,57 +360,62 @@ operator==(const sub_match& lhs, typename iterator_traits::value_type const* rhs); -template +template // Since C++20 + auto + operator<=>(const sub_match& lhs, + typename iterator_traits::value_type const* rhs); + +emplate // Removed in C++20 bool operator!=(const sub_match& lhs, typename iterator_traits::value_type const* rhs); -template +template // Removed in C++20 bool operator<(const sub_match& lhs, typename iterator_traits::value_type const* rhs); -template +template // Removed in C++20 bool operator>(const sub_match& lhs, typename iterator_traits::value_type const* rhs); -template +template // Removed in C++20 bool operator>=(const sub_match& lhs, typename iterator_traits::value_type const* rhs); -template +template // Removed in C++20 bool operator<=(const sub_match& lhs, typename iterator_traits::value_type const* rhs); -template +template // Removed in C++20 bool operator==(typename iterator_traits::value_type const& lhs, const sub_match& rhs); -template +template // Removed in C++20 bool operator!=(typename iterator_traits::value_type const& lhs, const sub_match& rhs); -template +template // Removed in C++20 bool operator<(typename iterator_traits::value_type const& lhs, const sub_match& rhs); -template +template // Removed in C++20 bool operator>(typename iterator_traits::value_type const& lhs, const sub_match& rhs); -template +template // Removed in C++20 bool operator>=(typename iterator_traits::value_type const& lhs, const sub_match& rhs); -template +template // Removed in C++20 bool operator<=(typename iterator_traits::value_type const& lhs, const sub_match& rhs); @@ -409,27 +425,32 @@ operator==(const sub_match& lhs, typename iterator_traits::value_type const& rhs); -template +template // Since C++20 + auto + operator<=>(const sub_match& lhs, + typename iterator_traits::value_type const& rhs); + +template // Removed in C++20 bool operator!=(const sub_match& lhs, typename iterator_traits::value_type const& rhs); -template +template // Removed in C++20 bool operator<(const sub_match& lhs, typename iterator_traits::value_type const& rhs); -template +template // Removed in C++20 bool operator>(const sub_match& lhs, typename iterator_traits::value_type const& rhs); -template +template // Removed in C++20 bool operator>=(const sub_match& lhs, typename iterator_traits::value_type const& rhs); -template +template // Removed in C++20 bool operator<=(const sub_match& lhs, typename iterator_traits::value_type const& rhs); @@ -5017,6 +5038,14 @@ return __x.compare(__y) == 0; } +#if _LIBCPP_STD_VER > 17 +template +using __submatch_cat = compare_three_way_result_t::value_type>>; +template +_LIBCPP_HIDE_FROM_ABI auto operator<=>(const sub_match<_BiIter>& __x, const sub_match<_BiIter>& __y) { + return static_cast<__submatch_cat<_BiIter>>(__x.compare(__y) <=> 0); +} +#else // _LIBCPP_STD_VER > 17 template inline _LIBCPP_INLINE_VISIBILITY bool @@ -5109,6 +5138,7 @@ { return !(__y < __x); } +#endif // _LIBCPP_STD_VER > 17 template inline _LIBCPP_INLINE_VISIBILITY @@ -5119,6 +5149,14 @@ return __x.compare(typename sub_match<_BiIter>::string_type(__y.data(), __y.size())) == 0; } +#if _LIBCPP_STD_VER > 17 +template +_LIBCPP_HIDE_FROM_ABI auto operator<=>( + const sub_match<_BiIter>& __x, const basic_string::value_type, _ST, _SA>& __y) { + return static_cast<__submatch_cat<_BiIter>>( + __x.compare(typename sub_match<_BiIter>::string_type(__y.data(), __y.size())) <=> 0); +} +#else // _LIBCPP_STD_VER > 17 template inline _LIBCPP_INLINE_VISIBILITY bool @@ -5216,6 +5254,7 @@ { return !(__y < __x); } +#endif // _LIBCPP_STD_VER > 17 template inline _LIBCPP_INLINE_VISIBILITY @@ -5226,6 +5265,13 @@ return __x.compare(__y) == 0; } +#if _LIBCPP_STD_VER > 17 +template +_LIBCPP_HIDE_FROM_ABI auto +operator<=>(const sub_match<_BiIter>& __x, typename iterator_traits<_BiIter>::value_type const* __y) { + return static_cast<__submatch_cat<_BiIter>>(__x.compare(__y) <=> 0); +} +#else // _LIBCPP_STD_VER > 17 template inline _LIBCPP_INLINE_VISIBILITY bool @@ -5326,6 +5372,7 @@ { return !(__y < __x); } +#endif // _LIBCPP_STD_VER > 17 template inline _LIBCPP_INLINE_VISIBILITY @@ -5337,6 +5384,14 @@ return __x.compare(string_type(1, __y)) == 0; } +#if _LIBCPP_STD_VER > 17 +template +_LIBCPP_HIDE_FROM_ABI auto +operator<=>(const sub_match<_BiIter>& __x, typename iterator_traits<_BiIter>::value_type const& __y) { + using string_type = basic_string::value_type>; + return static_cast<__submatch_cat<_BiIter>>(__x.compare(string_type(1, __y)) <=> 0); +} +#else // _LIBCPP_STD_VER > 17 template inline _LIBCPP_INLINE_VISIBILITY bool @@ -5382,6 +5437,7 @@ { return !(__y < __x); } +#endif // _LIBCPP_STD_VER > 17 template 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 --- 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 sub_match; +// Note in C++20 several of these operators have been removed and implicitly +// generated by the compiler using operator== and operator<=>. + // template // bool // operator==(const sub_match& lhs, const sub_match& rhs); @@ -212,14 +215,40 @@ // operator<=(const sub_match& lhs, // typename iterator_traits::value_type const& rhs); +// Added in C++20 +// template +// auto +// operator<=>(const sub_match& lhs, const sub_match& rhs); +// template +// auto +// operator<=>(const sub_match& lhs, +// const basic_string::value_type, ST, SA>& rhs); +// +// template +// auto +// operator<=>(const sub_match& lhs, +// typename iterator_traits::value_type const* rhs); +// +// template +// auto +// operator<=>(const sub_match& lhs, +// typename iterator_traits::value_type const& rhs); + #include #include + #include "test_macros.h" +#include "test_comparisons.h" template void test(const std::basic_string& x, const std::basic_string& y, bool doCStrTests = true) { +#if TEST_STD_VER >17 + AssertOrderReturn>(); +#else + AssertCompareReturnBool>(); +#endif typedef std::basic_string string; typedef std::sub_match sub_match; sub_match sm1; @@ -236,18 +265,27 @@ assert((sm1 > sm2) == (x > y)); assert((sm1 <= sm2) == (x <= y)); assert((sm1 >= sm2) == (x >= y)); +#if TEST_STD_VER >17 + assert(testOrder(sm1, sm2, x <=> y)); +#endif 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)); +#if TEST_STD_VER >17 + assert(testOrder(x, sm2, x <=> y)); +#endif 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)); +#if TEST_STD_VER >17 + assert(testOrder(sm1, y, x <=> y)); +#endif if (doCStrTests) { assert((x.c_str() == sm2) == (x == y)); assert((x.c_str() != sm2) == (x != y)); @@ -255,12 +293,18 @@ assert((x.c_str() > sm2) == (x > y)); assert((x.c_str() <= sm2) == (x <= y)); assert((x.c_str() >= sm2) == (x >= y)); +#if TEST_STD_VER >17 + assert(testOrder(x.c_str(), sm2, x <=> y)); +#endif 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)); +#if TEST_STD_VER >17 + assert(testOrder(sm1, y.c_str(), x <=> y)); +#endif } assert((x[0] == sm2) == (string(1, x[0]) == y)); assert((x[0] != sm2) == (string(1, x[0]) != y)); @@ -268,12 +312,18 @@ 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)); +#if TEST_STD_VER >17 + assert(testOrder(x[0], sm2, (string(1, x[0]) <=> y))); +#endif 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]))); +#if TEST_STD_VER >17 + assert(testOrder(sm1, y[0], x <=> (string(1, y[0])))); +#endif } int main(int, char**)