diff --git a/stl/inc/array b/stl/inc/array index 23c892f3a15..f8dae919a60 100644 --- a/stl/inc/array +++ b/stl/inc/array @@ -111,6 +111,11 @@ public: return _Ptr == _Right._Ptr; } +#if _HAS_CXX20 + _NODISCARD constexpr strong_ordering operator<=>(const _Array_const_iterator& _Right) const noexcept { + return _Ptr <=> _Right._Ptr; + } +#else // ^^^ _HAS_CXX20 ^^^ / vvv !_HAS_CXX20 vvv _NODISCARD _CONSTEXPR17 bool operator!=(const _Array_const_iterator& _Right) const noexcept { return !(*this == _Right); } @@ -130,6 +135,7 @@ public: _NODISCARD _CONSTEXPR17 bool operator>=(const _Array_const_iterator& _Right) const noexcept { return !(*this < _Right); } +#endif // !_HAS_CXX20 using _Prevent_inheriting_unwrap = _Array_const_iterator; @@ -235,6 +241,12 @@ private: return _Idx == _Right._Idx; } +#if _HAS_CXX20 + _NODISCARD constexpr strong_ordering operator<=>(const _Array_const_iterator& _Right) const noexcept { + _Compat(_Right); + return _Idx <=> _Right._Idx; + } +#else // ^^^ _HAS_CXX20 ^^^ / vvv !_HAS_CXX20 vvv _NODISCARD _CONSTEXPR17 bool operator!=(const _Array_const_iterator& _Right) const noexcept { return !(*this == _Right); } @@ -255,6 +267,7 @@ private: _NODISCARD _CONSTEXPR17 bool operator>=(const _Array_const_iterator& _Right) const noexcept { return !(*this < _Right); } +#endif // !_HAS_CXX20 _CONSTEXPR17 void _Compat(const _Array_const_iterator& _Right) const noexcept { // test for compatible iterator pair _STL_VERIFY(_Ptr == _Right._Ptr, "array iterators incompatible"); @@ -784,7 +797,7 @@ _NODISCARD _CONSTEXPR20 bool operator==(const array<_Ty, _Size>& _Left, const ar #if !_HAS_CXX20 template -_NODISCARD _CONSTEXPR20 bool operator!=(const array<_Ty, _Size>& _Left, const array<_Ty, _Size>& _Right) { +_NODISCARD bool operator!=(const array<_Ty, _Size>& _Left, const array<_Ty, _Size>& _Right) { return !(_Left == _Right); } #endif // !_HAS_CXX20 diff --git a/stl/inc/deque b/stl/inc/deque index fe0b478bda0..f1580180c88 100644 --- a/stl/inc/deque +++ b/stl/inc/deque @@ -107,6 +107,11 @@ public: return _Myoff == _Right._Myoff; } +#if _HAS_CXX20 + _NODISCARD strong_ordering operator<=>(const _Deque_unchecked_const_iterator& _Right) const noexcept { + return _Myoff <=> _Right._Myoff; + } +#else // ^^^ _HAS_CXX20 ^^^ / vvv !_HAS_CXX20 vvv _NODISCARD bool operator!=(const _Deque_unchecked_const_iterator& _Right) const noexcept { return !(*this == _Right); } @@ -126,6 +131,7 @@ public: _NODISCARD bool operator>=(const _Deque_unchecked_const_iterator& _Right) const noexcept { return !(*this < _Right); } +#endif // !_HAS_CXX20 const _Container_base12* _Getcont() const noexcept { // get container pointer return _Mycont; @@ -345,6 +351,12 @@ public: return this->_Myoff == _Right._Myoff; } +#if _HAS_CXX20 + _NODISCARD strong_ordering operator<=>(const _Deque_const_iterator& _Right) const noexcept { + _Compat(_Right); + return this->_Myoff <=> _Right._Myoff; + } +#else // ^^^ _HAS_CXX20 ^^^ / vvv !_HAS_CXX20 vvv _NODISCARD bool operator!=(const _Deque_const_iterator& _Right) const noexcept { return !(*this == _Right); } @@ -365,6 +377,7 @@ public: _NODISCARD bool operator>=(const _Deque_const_iterator& _Right) const noexcept { return !(*this < _Right); } +#endif // !_HAS_CXX20 void _Compat(const _Deque_const_iterator& _Right) const noexcept { // test for compatible iterator pair #if _ITERATOR_DEBUG_LEVEL == 0 diff --git a/stl/inc/filesystem b/stl/inc/filesystem index 075a08b1587..05341d65c4c 100644 --- a/stl/inc/filesystem +++ b/stl/inc/filesystem @@ -1603,9 +1603,11 @@ namespace filesystem { return _Lhs._Position == _Rhs._Position; } +#if !_HAS_CXX20 _NODISCARD friend bool operator!=(const _Path_iterator& _Lhs, const _Path_iterator& _Rhs) { return _Lhs._Position != _Rhs._Position; } +#endif // !_HAS_CXX20 #if _ITERATOR_DEBUG_LEVEL != 0 friend void _Verify_range(const _Path_iterator& _Lhs, const _Path_iterator& _Rhs) { @@ -2728,9 +2730,11 @@ namespace filesystem { return _Impl == _Rhs._Impl; } +#if !_HAS_CXX20 _NODISCARD bool operator!=(const directory_iterator& _Rhs) const noexcept /* strengthened */ { return _Impl != _Rhs._Impl; } +#endif // !_HAS_CXX20 _Directory_entry_proxy operator++(int) { _Directory_entry_proxy _Proxy(**this); @@ -2977,9 +2981,11 @@ namespace filesystem { return _Impl == _Rhs._Impl; } +#if !_HAS_CXX20 _NODISCARD bool operator!=(const recursive_directory_iterator& _Rhs) const noexcept { return _Impl != _Rhs._Impl; } +#endif // !_HAS_CXX20 _Directory_entry_proxy operator++(int) { _Directory_entry_proxy _Proxy(**this); diff --git a/stl/inc/forward_list b/stl/inc/forward_list index 935574d1004..468f6e9c139 100644 --- a/stl/inc/forward_list +++ b/stl/inc/forward_list @@ -63,17 +63,21 @@ public: return _Ptr == _Right._Ptr; } +#if !_HAS_CXX20 _NODISCARD bool operator!=(const _Flist_unchecked_const_iterator& _Right) const noexcept { return !(*this == _Right); } +#endif // !_HAS_CXX20 _NODISCARD bool operator==(_Default_sentinel) const noexcept { return _Ptr == nullptr; } +#if !_HAS_CXX20 _NODISCARD bool operator!=(_Default_sentinel) const noexcept { return _Ptr != nullptr; } +#endif // !_HAS_CXX20 _Nodeptr _Ptr; // pointer to node }; @@ -161,9 +165,11 @@ public: return this->_Ptr == _Right._Ptr; } +#if !_HAS_CXX20 _NODISCARD bool operator!=(const _Flist_const_iterator& _Right) const noexcept { return !(*this == _Right); } +#endif // !_HAS_CXX20 #if _ITERATOR_DEBUG_LEVEL == 2 friend void _Verify_range(const _Flist_const_iterator& _First, const _Flist_const_iterator& _Last) noexcept { diff --git a/stl/inc/iterator b/stl/inc/iterator index 94210f0eeb7..6fd2233e372 100644 --- a/stl/inc/iterator +++ b/stl/inc/iterator @@ -1496,6 +1496,13 @@ public: return _Myindex == _Right._Myindex; } +#if _HAS_CXX20 + _NODISCARD constexpr _STD strong_ordering operator<=>(const checked_array_iterator& _Right) const noexcept { + _STL_VERIFY(_Myarray == _Right._Myarray && _Mysize == _Right._Mysize, + "cannot compare incompatible checked_array_iterators"); + return _Myindex <=> _Right._Myindex; + } +#else // ^^^ _HAS_CXX20 ^^^ / vvv !_HAS_CXX20 vvv _NODISCARD constexpr bool operator!=(const checked_array_iterator& _Right) const noexcept { return !(*this == _Right); } @@ -1517,6 +1524,7 @@ public: _NODISCARD constexpr bool operator>=(const checked_array_iterator& _Right) const noexcept { return !(*this < _Right); } +#endif // !_HAS_CXX20 friend constexpr void _Verify_range( const checked_array_iterator& _First, const checked_array_iterator& _Last) noexcept { @@ -1650,6 +1658,11 @@ public: return _Myptr == _Right._Myptr; } +#if _HAS_CXX20 + _NODISCARD constexpr _STD strong_ordering operator<=>(const unchecked_array_iterator& _Right) const noexcept { + return _Myptr <=> _Right._Myptr; + } +#else // ^^^ _HAS_CXX20 ^^^ / vvv !_HAS_CXX20 vvv _NODISCARD constexpr bool operator!=(const unchecked_array_iterator& _Right) const noexcept { return !(*this == _Right); } @@ -1669,6 +1682,7 @@ public: _NODISCARD constexpr bool operator>=(const unchecked_array_iterator& _Right) const noexcept { return !(*this < _Right); } +#endif // !_HAS_CXX20 #if _ITERATOR_DEBUG_LEVEL != 0 friend constexpr void _Verify_range( diff --git a/stl/inc/list b/stl/inc/list index c8d81b1897e..812c81f6c61 100644 --- a/stl/inc/list +++ b/stl/inc/list @@ -74,9 +74,11 @@ public: return _Ptr == _Right._Ptr; } +#if !_HAS_CXX20 _NODISCARD bool operator!=(const _List_unchecked_const_iterator& _Right) const noexcept { return !(*this == _Right); } +#endif // !_HAS_CXX20 _Nodeptr _Ptr; // pointer to node }; @@ -199,9 +201,11 @@ public: return this->_Ptr == _Right._Ptr; } +#if !_HAS_CXX20 _NODISCARD bool operator!=(const _List_const_iterator& _Right) const noexcept { return !(*this == _Right); } +#endif // !_HAS_CXX20 #if _ITERATOR_DEBUG_LEVEL == 2 friend void _Verify_range(const _List_const_iterator& _First, const _List_const_iterator& _Last) noexcept { diff --git a/stl/inc/vector b/stl/inc/vector index 5ee01bc5ff2..a5b750af657 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -152,26 +152,33 @@ public: return _Ptr == _Right._Ptr; } - _NODISCARD _CONSTEXPR20_CONTAINER bool operator!=(const _Vector_const_iterator& _Right) const noexcept { +#if _HAS_CXX20 + _NODISCARD _CONSTEXPR20_CONTAINER strong_ordering operator<=>(const _Vector_const_iterator& _Right) const noexcept { + _Compat(_Right); + return _Unfancy(_Ptr) <=> _Unfancy(_Right._Ptr); + } +#else // ^^^ _HAS_CXX20 ^^^ / vvv !_HAS_CXX20 vvv + _NODISCARD bool operator!=(const _Vector_const_iterator& _Right) const noexcept { return !(*this == _Right); } - _NODISCARD _CONSTEXPR20_CONTAINER bool operator<(const _Vector_const_iterator& _Right) const noexcept { + _NODISCARD bool operator<(const _Vector_const_iterator& _Right) const noexcept { _Compat(_Right); return _Ptr < _Right._Ptr; } - _NODISCARD _CONSTEXPR20_CONTAINER bool operator>(const _Vector_const_iterator& _Right) const noexcept { + _NODISCARD bool operator>(const _Vector_const_iterator& _Right) const noexcept { return _Right < *this; } - _NODISCARD _CONSTEXPR20_CONTAINER bool operator<=(const _Vector_const_iterator& _Right) const noexcept { + _NODISCARD bool operator<=(const _Vector_const_iterator& _Right) const noexcept { return !(_Right < *this); } - _NODISCARD _CONSTEXPR20_CONTAINER bool operator>=(const _Vector_const_iterator& _Right) const noexcept { + _NODISCARD bool operator>=(const _Vector_const_iterator& _Right) const noexcept { return !(*this < _Right); } +#endif // !_HAS_CXX20 _CONSTEXPR20_CONTAINER void _Compat(const _Vector_const_iterator& _Right) const noexcept { // test for compatible iterator pair @@ -1851,7 +1858,7 @@ _NODISCARD _CONSTEXPR20_CONTAINER bool operator==(const vector<_Ty, _Alloc>& _Le #if !_HAS_CXX20 template -_NODISCARD _CONSTEXPR20_CONTAINER bool operator!=(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { +_NODISCARD bool operator!=(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { return !(_Left == _Right); } #endif // !_HAS_CXX20 @@ -2204,26 +2211,36 @@ public: return this->_Myptr == _Right._Myptr && this->_Myoff == _Right._Myoff; } - _NODISCARD _CONSTEXPR20_CONTAINER bool operator!=(const _Vb_const_iterator& _Right) const noexcept { +#if _HAS_CXX20 + _NODISCARD _CONSTEXPR20_CONTAINER strong_ordering operator<=>(const _Vb_const_iterator& _Right) const noexcept { + _Compat(_Right); + if (const auto _CmpResult = this->_Myptr <=> _Right._Myptr; _CmpResult != 0) { + return _CmpResult; + } + return this->_Myoff <=> _Right._Myoff; + } +#else // ^^^ _HAS_CXX20 ^^^ / vvv !_HAS_CXX20 vvv + _NODISCARD bool operator!=(const _Vb_const_iterator& _Right) const noexcept { return !(*this == _Right); } - _NODISCARD _CONSTEXPR20_CONTAINER bool operator<(const _Vb_const_iterator& _Right) const noexcept { + _NODISCARD bool operator<(const _Vb_const_iterator& _Right) const noexcept { _Compat(_Right); return this->_Myptr < _Right._Myptr || (this->_Myptr == _Right._Myptr && this->_Myoff < _Right._Myoff); } - _NODISCARD _CONSTEXPR20_CONTAINER bool operator>(const _Vb_const_iterator& _Right) const noexcept { + _NODISCARD bool operator>(const _Vb_const_iterator& _Right) const noexcept { return _Right < *this; } - _NODISCARD _CONSTEXPR20_CONTAINER bool operator<=(const _Vb_const_iterator& _Right) const noexcept { + _NODISCARD bool operator<=(const _Vb_const_iterator& _Right) const noexcept { return !(_Right < *this); } - _NODISCARD _CONSTEXPR20_CONTAINER bool operator>=(const _Vb_const_iterator& _Right) const noexcept { + _NODISCARD bool operator>=(const _Vb_const_iterator& _Right) const noexcept { return !(*this < _Right); } +#endif // !_HAS_CXX20 _CONSTEXPR20_CONTAINER void _Compat(const _Vb_const_iterator& _Right) const noexcept { // test for compatible iterator pair diff --git a/stl/inc/xhash b/stl/inc/xhash index 3c8a7bbaba2..a7fc07566a0 100644 --- a/stl/inc/xhash +++ b/stl/inc/xhash @@ -196,12 +196,14 @@ struct _Reinterpret_move_iter { return _Lhs._Base == _Rhs._Base; } +#if !_HAS_CXX20 #ifndef __CUDACC__ // TRANSITION, VSO-568006 _NODISCARD #endif // TRANSITION, VSO-568006 friend bool operator!=(const _Reinterpret_move_iter& _Lhs, const _Reinterpret_move_iter& _Rhs) { return _Lhs._Base != _Rhs._Base; } +#endif // !_HAS_CXX20 }; // STRUCT TEMPLATE _List_head_construct_ptr diff --git a/stl/inc/xstring b/stl/inc/xstring index c5fc7e1c89f..8551a274080 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -1124,6 +1124,17 @@ public: #endif // _ITERATOR_DEBUG_LEVEL } +#if _HAS_CXX20 + _NODISCARD constexpr strong_ordering operator<=>(const _String_view_iterator& _Right) const noexcept { +#if _ITERATOR_DEBUG_LEVEL >= 1 + _STL_VERIFY(_Mydata == _Right._Mydata && _Mysize == _Right._Mysize, + "cannot compare incompatible string_view iterators"); + return _Myoff <=> _Right._Myoff; +#else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 ^^^ // vvv _ITERATOR_DEBUG_LEVEL == 0 vvv + return _Myptr <=> _Right._Myptr; +#endif // _ITERATOR_DEBUG_LEVEL + } +#else // ^^^ _HAS_CXX20 ^^^ / vvv !_HAS_CXX20 vvv _NODISCARD constexpr bool operator!=(const _String_view_iterator& _Right) const noexcept { return !(*this == _Right); } @@ -1149,6 +1160,7 @@ public: _NODISCARD constexpr bool operator>=(const _String_view_iterator& _Right) const noexcept { return !(*this < _Right); } +#endif // !_HAS_CXX20 #if _ITERATOR_DEBUG_LEVEL >= 1 friend constexpr void _Verify_range(const _String_view_iterator& _First, const _String_view_iterator& _Last) { @@ -2009,6 +2021,12 @@ public: return _Ptr == _Right._Ptr; } +#if _HAS_CXX20 + _NODISCARD strong_ordering operator<=>(const _String_const_iterator& _Right) const noexcept { + _Compat(_Right); + return _Unfancy(_Ptr) <=> _Unfancy(_Right._Ptr); + } +#else // ^^^ _HAS_CXX20 ^^^ / vvv !_HAS_CXX20 vvv _NODISCARD bool operator!=(const _String_const_iterator& _Right) const noexcept { return !(*this == _Right); } @@ -2029,6 +2047,7 @@ public: _NODISCARD bool operator>=(const _String_const_iterator& _Right) const noexcept { return !(*this < _Right); } +#endif // !_HAS_CXX20 void _Compat(const _String_const_iterator& _Right) const noexcept { // test for compatible iterator pair #if _ITERATOR_DEBUG_LEVEL >= 1 diff --git a/stl/inc/xtree b/stl/inc/xtree index aba7f46baee..3d9e6786ee0 100644 --- a/stl/inc/xtree +++ b/stl/inc/xtree @@ -98,18 +98,22 @@ public: return _Ptr == _Right._Ptr; } +#if !_HAS_CXX20 _NODISCARD bool operator!=(const _Tree_unchecked_const_iterator& _Right) const noexcept { return !(*this == _Right); } +#endif // !_HAS_CXX20 _NODISCARD bool operator==(_Default_sentinel) const noexcept { return !!_Ptr->_Isnil; // TRANSITION, avoid warning C4800: // "Implicit conversion from 'char' to bool. Possible information loss" (/Wall) } +#if !_HAS_CXX20 _NODISCARD bool operator!=(_Default_sentinel) const noexcept { return !_Ptr->_Isnil; } +#endif // !_HAS_CXX20 _Nodeptr _Ptr; // pointer to node }; @@ -232,9 +236,11 @@ public: return this->_Ptr == _Right._Ptr; } +#if !_HAS_CXX20 _NODISCARD bool operator!=(const _Tree_const_iterator& _Right) const noexcept { return !(*this == _Right); } +#endif // !_HAS_CXX20 #if _ITERATOR_DEBUG_LEVEL == 2 friend void _Verify_range(const _Tree_const_iterator& _First, const _Tree_const_iterator& _Last) noexcept { diff --git a/tests/std/tests/P1614R2_spaceship/test.cpp b/tests/std/tests/P1614R2_spaceship/test.cpp index 01b773ad200..2bd59ee057b 100644 --- a/tests/std/tests/P1614R2_spaceship/test.cpp +++ b/tests/std/tests/P1614R2_spaceship/test.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -179,6 +180,27 @@ void unordered_containers_test( assert(something != different); } +template +void ordered_iterator_test(const Iter& smaller, const Iter& smaller_equal, const Iter& larger, + const ConstIter& const_smaller, const ConstIter& const_smaller_equal, const ConstIter& const_larger) { + spaceship_test(smaller, smaller_equal, larger); + spaceship_test(const_smaller, const_smaller_equal, const_larger); + spaceship_test(const_smaller, smaller_equal, larger); +} + +template +void unordered_iterator_test(const Iter& something, const Iter& something_equal, const Iter& different, + const ConstIter& const_something, const ConstIter& const_something_equal, const ConstIter& const_different) { + assert(something == something_equal); + assert(something != different); + + assert(const_something == const_something_equal); + assert(const_something != const_different); + + assert(something == const_something_equal); + assert(something != const_different); +} + template void diagnostics_test() { dummy_diagnostic c_mem[2]; @@ -233,61 +255,72 @@ void ordering_test_cases() { std::array a2 = {100, 100, 100}; std::array b1 = {200, 200}; ordered_containers_test(a1, a2, b1); + ordered_iterator_test(a1.begin(), a1.begin(), a1.end(), a1.cbegin(), a1.cbegin(), a1.cend()); } { // array SynthOrdered std::array a = {10, 20, 30}; std::array b = {10, 20, 40}; ordered_containers_test(a, a, b); + ordered_iterator_test(a.begin(), a.begin(), a.end(), a.cbegin(), a.cbegin(), a.cend()); } { // deque std::deque a1(3, 100); std::deque a2(3, 100); std::deque b1(2, 200); ordered_containers_test(a1, a2, b1); + ordered_iterator_test(a1.begin(), a1.begin(), a1.end(), a1.cbegin(), a1.cbegin(), a1.cend()); } { // deque SynthOrdered std::deque a = {10, 20, 30}; std::deque b = {10, 20, 40}; ordered_containers_test(a, a, b); + ordered_iterator_test(a.begin(), a.begin(), a.end(), a.cbegin(), a.cbegin(), a.cend()); } { // list std::list a1(3, 100); std::list a2(3, 100); std::list b1(2, 200); ordered_containers_test(a1, a2, b1); + unordered_iterator_test(a1.begin(), a1.begin(), a1.end(), a1.cbegin(), a1.cbegin(), a1.cend()); } { // list SynthOrdered std::list a = {10, 20, 30}; std::list b = {10, 20, 40}; ordered_containers_test(a, a, b); + unordered_iterator_test(a.begin(), a.begin(), a.end(), a.cbegin(), a.cbegin(), a.cend()); } { // vector std::vector a1(3, 100); std::vector a2(3, 100); std::vector b1(2, 200); ordered_containers_test(a1, a2, b1); + ordered_iterator_test(a1.begin(), a1.begin(), a1.end(), a1.cbegin(), a1.cbegin(), a1.cend()); } { // vector SynthOrdered std::vector a = {10, 20, 30}; std::vector b = {10, 20, 40}; ordered_containers_test(a, a, b); + ordered_iterator_test(a.begin(), a.begin(), a.end(), a.cbegin(), a.cbegin(), a.cend()); } { // vector std::vector c1 = {false, true, false}; std::vector c2 = {false, true, false}; std::vector d1 = {true, false}; ordered_containers_test(c1, c2, d1); + ordered_iterator_test(c1.begin(), c1.begin(), c1.end(), c1.cbegin(), c1.cbegin(), c1.cend()); } { // forward_list std::forward_list a1(3, 100); std::forward_list a2(3, 100); std::forward_list b1(2, 200); ordered_containers_test(a1, a2, b1); + unordered_iterator_test(a1.begin(), a1.begin(), a1.end(), a1.cbegin(), a1.cbegin(), a1.cend()); } { // forward_list SynthOrdered std::forward_list a = {10, 20, 30}; std::forward_list b = {10, 20, 40}; ordered_containers_test(a, a, b); + unordered_iterator_test(a.begin(), a.begin(), a.end(), a.cbegin(), a.cbegin(), a.cend()); } { // map std::map a1; @@ -300,22 +333,26 @@ void ordering_test_cases() { b1["zoe"] = 3; b1["koala"] = 4; ordered_containers_test(a1, a2, b1); + unordered_iterator_test(a1.begin(), a1.begin(), a1.end(), a1.cbegin(), a1.cbegin(), a1.cend()); } { // map SynthOrdered std::map a = {{10, 'z'}, {20, 'z'}, {30, 'z'}}; std::map b = {{10, 'z'}, {20, 'z'}, {40, 'z'}}; ordered_containers_test(a, a, b); + unordered_iterator_test(a.begin(), a.begin(), a.end(), a.cbegin(), a.cbegin(), a.cend()); } { // multimap std::multimap a1 = {{'a', 1}, {'b', 2}, {'a', 3}}; std::multimap a2 = {{'a', 1}, {'a', 3}, {'b', 2}}; std::multimap b1 = {{'z', 4}, {'y', 90}, {'z', 12}}; ordered_containers_test(a1, a2, b1); + unordered_iterator_test(a1.begin(), a1.begin(), a1.end(), a1.cbegin(), a1.cbegin(), a1.cend()); } { // multimap SynthOrdered std::multimap a = {{10, 'z'}, {20, 'z'}, {30, 'z'}}; std::multimap b = {{10, 'z'}, {20, 'z'}, {40, 'z'}}; ordered_containers_test(a, a, b); + unordered_iterator_test(a.begin(), a.begin(), a.end(), a.cbegin(), a.cbegin(), a.cend()); } { // set std::set a1; @@ -330,11 +367,13 @@ void ordering_test_cases() { b1.insert(30); b1.insert(40); ordered_containers_test(a1, a2, b1); + unordered_iterator_test(a1.begin(), a1.begin(), a1.end(), a1.cbegin(), a1.cbegin(), a1.cend()); } { // set SynthOrdered std::set a = {10, 20, 30}; std::set b = {10, 20, 40}; ordered_containers_test(a, a, b); + unordered_iterator_test(a.begin(), a.begin(), a.end(), a.cbegin(), a.cbegin(), a.cend()); } { // multiset std::multiset a1; @@ -352,11 +391,13 @@ void ordering_test_cases() { b1.insert(40); b1.insert(40); ordered_containers_test(a1, a2, b1); + unordered_iterator_test(a1.begin(), a1.begin(), a1.end(), a1.cbegin(), a1.cbegin(), a1.cend()); } { // multiset SynthOrdered std::multiset a = {10, 20, 30}; std::multiset b = {10, 20, 40}; ordered_containers_test(a, a, b); + unordered_iterator_test(a.begin(), a.begin(), a.end(), a.cbegin(), a.cbegin(), a.cend()); } { // unordered_map using stringmap = std::unordered_map; @@ -364,6 +405,7 @@ void ordering_test_cases() { stringmap b = {{"dog", "poodle"}, {"bear", "grizzly"}, {"cat", "tabby"}}; stringmap c = {{"cat", "siamese"}, {"dog", "lab"}, {"bear", "polar"}}; unordered_containers_test(a, b, c); + unordered_iterator_test(a.begin(), a.begin(), a.end(), a.cbegin(), a.cbegin(), a.cend()); } { // unordered_multimap using stringmap = std::unordered_multimap; @@ -371,18 +413,21 @@ void ordering_test_cases() { stringmap b = {{"dog", "poodle"}, {"cat", "siamese"}, {"cat", "tabby"}, {"dog", "poodle"}}; stringmap c = {{"cat", "siamese"}, {"dog", "lab"}, {"bear", "polar"}}; unordered_containers_test(a, b, c); + unordered_iterator_test(a.begin(), a.begin(), a.end(), a.cbegin(), a.cbegin(), a.cend()); } { // unordered_set std::unordered_set a = {"cat", "dog", "bear"}; std::unordered_set b = {"bear", "cat", "dog"}; std::unordered_set c = {"mouse", "cat", "bear", "dog"}; unordered_containers_test(a, b, c); + unordered_iterator_test(a.begin(), a.begin(), a.end(), a.cbegin(), a.cbegin(), a.cend()); } { // unordered_multiset std::unordered_multiset a = {"cat", "dog", "cat"}; std::unordered_multiset b = {"cat", "cat", "dog"}; std::unordered_multiset c = {"mouse", "cat", "bear", "dog"}; unordered_containers_test(a, b, c); + unordered_iterator_test(a.begin(), a.begin(), a.end(), a.cbegin(), a.cbegin(), a.cend()); } { // queue std::deque deq1(3, 100); @@ -414,6 +459,36 @@ void ordering_test_cases() { std::stack b{std::deque{10, 20, 40}}; ordered_containers_test(a, a, b); } + { // checked_array_iterator + int arr[] = {11, 22, 33}; + constexpr auto N = std::size(arr); + + using I = stdext::checked_array_iterator; + using CI = stdext::checked_array_iterator; // TRANSITION, GH-943, should be + + I first{arr, N}; + I last{arr, N, N}; + + CI cfirst{arr, N}; + CI clast{arr, N, N}; + + ordered_iterator_test(first, first, last, cfirst, cfirst, clast); + } + { // unchecked_array_iterator + int arr[] = {11, 22, 33}; + constexpr auto N = std::size(arr); + + using I = stdext::unchecked_array_iterator; + using CI = stdext::unchecked_array_iterator; // TRANSITION, GH-943, should be + + I first{arr}; + I last{arr + N}; + + CI cfirst{arr}; + CI clast{arr + N}; + + ordered_iterator_test(first, first, last, cfirst, cfirst, clast); + } { // sub_match const std::string s1{"cats"}; const std::string s2{"meow"}; @@ -501,6 +576,13 @@ void ordering_test_cases() { assert(("abcdef" <=> a1) == std::strong_ordering::equivalent); assert(("zebra" <=> a1) == std::strong_ordering::greater); } + { // string iterators + std::string a1 = "aaa"; + std::string a2 = "aaa"; + std::string b1 = "bb"; + ordered_containers_test(a1, a2, b1); + ordered_iterator_test(a1.begin(), a1.begin(), a1.end(), a1.cbegin(), a1.cbegin(), a1.cend()); + } { // string_view const std::string_view a1 = "abcdef"; const std::string_view a2 = "abcdef"; @@ -577,6 +659,13 @@ void ordering_test_cases() { static_assert(("abcdef" <=> a1) == std::strong_ordering::equivalent); static_assert(("zebra" <=> a1) == std::strong_ordering::greater); } + { // string_view iterators + std::string_view a1 = "aaa"; + std::string_view a2 = "aaa"; + std::string_view b1 = "bb"; + ordered_containers_test(a1, a2, b1); + ordered_iterator_test(a1.begin(), a1.begin(), a1.end(), a1.cbegin(), a1.cbegin(), a1.cend()); + } { // Diagnostics Library diagnostics_test(); diagnostics_test(); @@ -676,6 +765,7 @@ void ordering_test_cases() { const std::filesystem::path p3{R"(a/b/d)"}; spaceship_test(p1, p2, p3); + unordered_containers_test(p1.begin(), p1.begin(), p1.end()); } { // filesystem::file_status std::filesystem::file_status s1;