diff --git a/stl/inc/array b/stl/inc/array index d51bc8f54b..98684f936a 100644 --- a/stl/inc/array +++ b/stl/inc/array @@ -577,6 +577,10 @@ public: return _Elems; } + // friend constexpr bool operator==(const array&, const array&) = default; + // friend constexpr _Synth_three_way_result operator<=>(const array&, const array&); + // friend constexpr bool operator<=>(const array&, const array&); + [[noreturn]] void _Xran() const { _Xout_of_range("invalid array subscript"); } @@ -778,6 +782,7 @@ _NODISCARD _CONSTEXPR20 bool operator==(const array<_Ty, _Size>& _Left, const ar return _STD equal(_Left.begin(), _Left.end(), _Right.begin()); } +#if !_HAS_CXX20 || __cpp_impl_three_way_comparison < 201902L template _NODISCARD _CONSTEXPR20 bool operator!=(const array<_Ty, _Size>& _Left, const array<_Ty, _Size>& _Right) { return !(_Left == _Right); @@ -802,6 +807,15 @@ template _NODISCARD _CONSTEXPR20 bool operator>=(const array<_Ty, _Size>& _Left, const array<_Ty, _Size>& _Right) { return !(_Left < _Right); } +#endif // !_HAS_CXX20 || __cpp_impl_three_way_comparison < 201902L + +#if defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts) +template +_NODISCARD _CONSTEXPR20 _Synth_three_way_result<_Ty> operator<=>( + const array<_Ty, _Size>& _Left, const array<_Ty, _Size>& _Right) { + return _STD lexicographical_compare_three_way(_Left.begin(), _Left.end(), _Right.begin(), _Right.end()); +} +#endif // defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts) #if _HAS_CXX20 // FUNCTION TEMPLATE to_array diff --git a/stl/inc/deque b/stl/inc/deque index 73a74b7a71..2e6e04f861 100644 --- a/stl/inc/deque +++ b/stl/inc/deque @@ -1581,6 +1581,7 @@ _NODISCARD bool operator==(const deque<_Ty, _Alloc>& _Left, const deque<_Ty, _Al && _STD equal(_Left._Unchecked_begin(), _Left._Unchecked_end(), _Right._Unchecked_begin()); } +#if !_HAS_CXX20 || __cpp_impl_three_way_comparison < 201902L template _NODISCARD bool operator!=(const deque<_Ty, _Alloc>& _Left, const deque<_Ty, _Alloc>& _Right) { return !(_Left == _Right); @@ -1606,6 +1607,15 @@ template _NODISCARD bool operator>=(const deque<_Ty, _Alloc>& _Left, const deque<_Ty, _Alloc>& _Right) { return !(_Left < _Right); } +#endif // !_HAS_CXX20 || __cpp_impl_three_way_comparison < 201902L + +#if defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts) +template +_NODISCARD _Synth_three_way_result<_Ty> operator<=>(const deque<_Ty, _Alloc>& _Left, const deque<_Ty, _Alloc>& _Right) { + return _STD lexicographical_compare_three_way(_Left._Unchecked_begin(), _Left._Unchecked_end(), + _Right._Unchecked_begin(), _Right._Unchecked_end(), _Synth_three_way{}); +} +#endif // defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts) #if _HAS_CXX20 template diff --git a/stl/inc/forward_list b/stl/inc/forward_list index 24227c66c4..3a33993ac6 100644 --- a/stl/inc/forward_list +++ b/stl/inc/forward_list @@ -1521,6 +1521,7 @@ _NODISCARD bool operator==(const forward_list<_Ty, _Alloc>& _Left, const forward return _STD equal(_Left.begin(), _Left.end(), _Right.begin(), _Right.end()); } +#if !_HAS_CXX20 || __cpp_impl_three_way_comparison < 201902L template _NODISCARD bool operator!=(const forward_list<_Ty, _Alloc>& _Left, const forward_list<_Ty, _Alloc>& _Right) { return !(_Left == _Right); @@ -1545,6 +1546,16 @@ template _NODISCARD bool operator>=(const forward_list<_Ty, _Alloc>& _Left, const forward_list<_Ty, _Alloc>& _Right) { return !(_Left < _Right); } +#endif // !_HAS_CXX20 || __cpp_impl_three_way_comparison < 201902L + +#if defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts) +template +_NODISCARD _Synth_three_way_result<_Ty> operator<=>( + const forward_list<_Ty, _Alloc>& _Left, const forward_list<_Ty, _Alloc>& _Right) { + return _STD lexicographical_compare_three_way( + _Left.begin(), _Left.end(), _Right.begin(), _Right.end(), _Synth_three_way{}); +} +#endif // defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts) #if _HAS_CXX20 template diff --git a/stl/inc/iterator b/stl/inc/iterator index fee3511a90..b2dc38e32b 100644 --- a/stl/inc/iterator +++ b/stl/inc/iterator @@ -292,11 +292,13 @@ _NODISCARD bool operator==(const istream_iterator<_Ty, _Elem, _Traits, _Diff>& _ return _Left._Equal(_Right); } +#if !_HAS_CXX20 || __cpp_impl_three_way_comparison < 201902L template _NODISCARD bool operator!=(const istream_iterator<_Ty, _Elem, _Traits, _Diff>& _Left, const istream_iterator<_Ty, _Elem, _Traits, _Diff>& _Right) { return !(_Left == _Right); } +#endif // !_HAS_CXX20 || __cpp_impl_three_way_comparison < 201902L // CLASS TEMPLATE ostream_iterator template > @@ -458,11 +460,13 @@ _NODISCARD bool operator==( return _Left.equal(_Right); } +#if !_HAS_CXX20 || __cpp_impl_three_way_comparison < 201902L template _NODISCARD bool operator!=( const istreambuf_iterator<_Elem, _Traits>& _Left, const istreambuf_iterator<_Elem, _Traits>& _Right) { return !(_Left == _Right); } +#endif // !_HAS_CXX20 || __cpp_impl_three_way_comparison < 201902L // CLASS TEMPLATE ostreambuf_iterator template diff --git a/stl/inc/list b/stl/inc/list index a223036db1..e20127cd77 100644 --- a/stl/inc/list +++ b/stl/inc/list @@ -1810,6 +1810,7 @@ _NODISCARD bool operator==(const list<_Ty, _Alloc>& _Left, const list<_Ty, _Allo return _Left.size() == _Right.size() && _STD equal(_Left.begin(), _Left.end(), _Right.begin()); } +#if !_HAS_CXX20 || __cpp_impl_three_way_comparison < 201902L template _NODISCARD bool operator!=(const list<_Ty, _Alloc>& _Left, const list<_Ty, _Alloc>& _Right) { return !(_Left == _Right); @@ -1834,6 +1835,15 @@ template _NODISCARD bool operator>=(const list<_Ty, _Alloc>& _Left, const list<_Ty, _Alloc>& _Right) { return !(_Left < _Right); } +#endif // !_HAS_CXX20 || __cpp_impl_three_way_comparison < 201902L + +#if defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts) +template +_NODISCARD _Synth_three_way_result<_Ty> operator<=>(const list<_Ty, _Alloc>& _Left, const list<_Ty, _Alloc>& _Right) { + return _STD lexicographical_compare_three_way( + _Left.begin(), _Left.end(), _Right.begin(), _Right.end(), _Synth_three_way{}); +} +#endif // defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts) #if _HAS_CXX20 template diff --git a/stl/inc/map b/stl/inc/map index f33f3df84f..fbfbc572bf 100644 --- a/stl/inc/map +++ b/stl/inc/map @@ -369,6 +369,7 @@ _NODISCARD bool operator==(const map<_Kty, _Ty, _Pr, _Alloc>& _Left, const map<_ && _STD equal(_Left._Unchecked_begin(), _Left._Unchecked_end_iter(), _Right._Unchecked_begin()); } +#if !_HAS_CXX20 || __cpp_impl_three_way_comparison < 201902L template _NODISCARD bool operator!=(const map<_Kty, _Ty, _Pr, _Alloc>& _Left, const map<_Kty, _Ty, _Pr, _Alloc>& _Right) { return !(_Left == _Right); @@ -394,6 +395,16 @@ template _NODISCARD bool operator>=(const map<_Kty, _Ty, _Pr, _Alloc>& _Left, const map<_Kty, _Ty, _Pr, _Alloc>& _Right) { return !(_Left < _Right); } +#endif // !_HAS_CXX20 || __cpp_impl_three_way_comparison < 201902L + +#if defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts) +template +_NODISCARD _Synth_three_way_result> operator<=>( + const map<_Kty, _Ty, _Pr, _Alloc>& _Left, const map<_Kty, _Ty, _Pr, _Alloc>& _Right) { + return _STD lexicographical_compare_three_way(_Left._Unchecked_begin(), _Left._Unchecked_end_iter(), + _Right._Unchecked_begin(), _Right._Unchecked_end_iter(), _Synth_three_way{}); +} +#endif // defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts) template void swap(map<_Kty, _Ty, _Pr, _Alloc>& _Left, map<_Kty, _Ty, _Pr, _Alloc>& _Right) noexcept( @@ -557,6 +568,7 @@ _NODISCARD bool operator==( && _STD equal(_Left._Unchecked_begin(), _Left._Unchecked_end_iter(), _Right._Unchecked_begin()); } +#if !_HAS_CXX20 || __cpp_impl_three_way_comparison < 201902L template _NODISCARD bool operator!=( const multimap<_Kty, _Ty, _Pr, _Alloc>& _Left, const multimap<_Kty, _Ty, _Pr, _Alloc>& _Right) { @@ -587,6 +599,16 @@ _NODISCARD bool operator>=( const multimap<_Kty, _Ty, _Pr, _Alloc>& _Left, const multimap<_Kty, _Ty, _Pr, _Alloc>& _Right) { return !(_Left < _Right); } +#endif // !_HAS_CXX20 || __cpp_impl_three_way_comparison < 201902L + +#if defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts) +template +_NODISCARD _Synth_three_way_result> operator<=>( + const multimap<_Kty, _Ty, _Pr, _Alloc>& _Left, const multimap<_Kty, _Ty, _Pr, _Alloc>& _Right) { + return _STD lexicographical_compare_three_way(_Left._Unchecked_begin(), _Left._Unchecked_end_iter(), + _Right._Unchecked_begin(), _Right._Unchecked_end_iter(), _Synth_three_way{}); +} +#endif // defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts) template void swap(multimap<_Kty, _Ty, _Pr, _Alloc>& _Left, multimap<_Kty, _Ty, _Pr, _Alloc>& _Right) noexcept( diff --git a/stl/inc/queue b/stl/inc/queue index 8954046397..d799bb51e1 100644 --- a/stl/inc/queue +++ b/stl/inc/queue @@ -54,6 +54,14 @@ _NODISCARD bool operator>=(const queue<_Ty, _Container>& _Left, const queue<_Ty, return _Left.c >= _Right.c; } +#if defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts) +template +_NODISCARD compare_three_way_result_t<_Container> operator<=>( + const queue<_Ty, _Container>& _Left, const queue<_Ty, _Container>& _Right) { + return _Left.c <=> _Right.c; +} +#endif // defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts) + template class queue { public: @@ -148,6 +156,7 @@ public: friend bool operator> <>(const queue&, const queue&); friend bool operator<= <>(const queue&, const queue&); friend bool operator>= <>(const queue&, const queue&); + friend compare_three_way_result_t<_Container> operator<=> <>(const queue&, const queue&); // clang-format on protected: diff --git a/stl/inc/set b/stl/inc/set index a049d279f2..2e1f397254 100644 --- a/stl/inc/set +++ b/stl/inc/set @@ -180,6 +180,7 @@ _NODISCARD bool operator==(const set<_Kty, _Pr, _Alloc>& _Left, const set<_Kty, && _STD equal(_Left._Unchecked_begin(), _Left._Unchecked_end_iter(), _Right._Unchecked_begin()); } +#if !_HAS_CXX20 || __cpp_impl_three_way_comparison < 201902L template _NODISCARD bool operator!=(const set<_Kty, _Pr, _Alloc>& _Left, const set<_Kty, _Pr, _Alloc>& _Right) { return !(_Left == _Right); @@ -205,6 +206,16 @@ template _NODISCARD bool operator>=(const set<_Kty, _Pr, _Alloc>& _Left, const set<_Kty, _Pr, _Alloc>& _Right) { return !(_Left < _Right); } +#endif // !_HAS_CXX20 || __cpp_impl_three_way_comparison < 201902L + +#if defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts) +template +_NODISCARD _Synth_three_way_result<_Kty> operator<=>( + const set<_Kty, _Pr, _Alloc>& _Left, const set<_Kty, _Pr, _Alloc>& _Right) { + return _STD lexicographical_compare_three_way(_Left._Unchecked_begin(), _Left._Unchecked_end_iter(), + _Right._Unchecked_begin(), _Right._Unchecked_end_iter(), _Synth_three_way{}); +} +#endif // defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts) template void swap(set<_Kty, _Pr, _Alloc>& _Left, set<_Kty, _Pr, _Alloc>& _Right) noexcept(noexcept(_Left.swap(_Right))) { @@ -352,6 +363,7 @@ _NODISCARD bool operator==(const multiset<_Kty, _Pr, _Alloc>& _Left, const multi && _STD equal(_Left._Unchecked_begin(), _Left._Unchecked_end_iter(), _Right._Unchecked_begin()); } +#if !_HAS_CXX20 || __cpp_impl_three_way_comparison < 201902L template _NODISCARD bool operator!=(const multiset<_Kty, _Pr, _Alloc>& _Left, const multiset<_Kty, _Pr, _Alloc>& _Right) { return !(_Left == _Right); @@ -377,6 +389,16 @@ template _NODISCARD bool operator>=(const multiset<_Kty, _Pr, _Alloc>& _Left, const multiset<_Kty, _Pr, _Alloc>& _Right) { return !(_Left < _Right); } +#endif // !_HAS_CXX20 || __cpp_impl_three_way_comparison < 201902L + +#if defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts) +template +_NODISCARD _Synth_three_way_result<_Kty> operator<=>( + const multiset<_Kty, _Pr, _Alloc>& _Left, const multiset<_Kty, _Pr, _Alloc>& _Right) { + return _STD lexicographical_compare_three_way(_Left._Unchecked_begin(), _Left._Unchecked_end_iter(), + _Right._Unchecked_begin(), _Right._Unchecked_end_iter(), _Synth_three_way{}); +} +#endif // defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts) template void swap(multiset<_Kty, _Pr, _Alloc>& _Left, multiset<_Kty, _Pr, _Alloc>& _Right) noexcept( diff --git a/stl/inc/stack b/stl/inc/stack index 55889064e8..f9b149f96b 100644 --- a/stl/inc/stack +++ b/stl/inc/stack @@ -52,6 +52,14 @@ _NODISCARD bool operator>=(const stack<_Ty, _Container>& _Left, const stack<_Ty, return _Left.c >= _Right.c; } +#if defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts) +template +_NODISCARD compare_three_way_result_t<_Container> operator<=>( + const stack<_Ty, _Container>& _Left, const stack<_Ty, _Container>& _Right) { + return _Left.c <=> _Right.c; +} +#endif // defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts) + template class stack { public: @@ -138,6 +146,7 @@ public: friend bool operator> <>(const stack&, const stack&); friend bool operator<= <>(const stack&, const stack&); friend bool operator>= <>(const stack&, const stack&); + friend compare_three_way_result_t<_Container> operator<=> <>(const stack&, const stack&); // clang-format on protected: diff --git a/stl/inc/unordered_map b/stl/inc/unordered_map index 0a564aaba2..d208165ab4 100644 --- a/stl/inc/unordered_map +++ b/stl/inc/unordered_map @@ -468,11 +468,13 @@ _NODISCARD bool operator==(const unordered_map<_Kty, _Ty, _Hasher, _Keyeq, _Allo return _Hash_equal(_Left, _Right); } +#if !_HAS_CXX20 || __cpp_impl_three_way_comparison < 201902L template _NODISCARD bool operator!=(const unordered_map<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>& _Left, const unordered_map<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>& _Right) { return !(_Left == _Right); } +#endif // !_HAS_CXX20 || __cpp_impl_three_way_comparison < 201902L // CLASS TEMPLATE unordered_multimap template , class _Keyeq = equal_to<_Kty>, @@ -758,11 +760,13 @@ _NODISCARD bool operator==(const unordered_multimap<_Kty, _Ty, _Hasher, _Keyeq, return _Hash_equal(_Left, _Right); } +#if !_HAS_CXX20 || __cpp_impl_three_way_comparison < 201902L template _NODISCARD bool operator!=(const unordered_multimap<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>& _Left, const unordered_multimap<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>& _Right) { return !(_Left == _Right); } +#endif // !_HAS_CXX20 || __cpp_impl_three_way_comparison < 201902L #if _HAS_TR1_NAMESPACE namespace _DEPRECATE_TR1_NAMESPACE tr1 { diff --git a/stl/inc/unordered_set b/stl/inc/unordered_set index 1f32080e23..59f9328b16 100644 --- a/stl/inc/unordered_set +++ b/stl/inc/unordered_set @@ -322,11 +322,13 @@ _NODISCARD bool operator==(const unordered_set<_Kty, _Hasher, _Keyeq, _Alloc>& _ return _Hash_equal(_Left, _Right); } +#if !_HAS_CXX20 || __cpp_impl_three_way_comparison < 201902L template _NODISCARD bool operator!=(const unordered_set<_Kty, _Hasher, _Keyeq, _Alloc>& _Left, const unordered_set<_Kty, _Hasher, _Keyeq, _Alloc>& _Right) { return !(_Left == _Right); } +#endif // !_HAS_CXX20 || __cpp_impl_three_way_comparison < 201902L // CLASS TEMPLATE unordered_multiset template , class _Keyeq = equal_to<_Kty>, class _Alloc = allocator<_Kty>> @@ -584,11 +586,13 @@ _NODISCARD bool operator==(const unordered_multiset<_Kty, _Hasher, _Keyeq, _Allo return _Hash_equal(_Left, _Right); } +#if !_HAS_CXX20 || __cpp_impl_three_way_comparison < 201902L template _NODISCARD bool operator!=(const unordered_multiset<_Kty, _Hasher, _Keyeq, _Alloc>& _Left, const unordered_multiset<_Kty, _Hasher, _Keyeq, _Alloc>& _Right) { return !(_Left == _Right); } +#endif // !_HAS_CXX20 || __cpp_impl_three_way_comparison < 201902L #if _HAS_TR1_NAMESPACE namespace _DEPRECATE_TR1_NAMESPACE tr1 { diff --git a/stl/inc/utility b/stl/inc/utility index f40b42623e..b013cb0f57 100644 --- a/stl/inc/utility +++ b/stl/inc/utility @@ -695,6 +695,58 @@ _NODISCARD constexpr bool cmp_greater_equal(const _Ty1 _Left, const _Ty2 _Right) return !_STD cmp_less(_Left, _Right); } +#if defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts) +// STRUCT TEMPLATE _Synth_three_way +template +struct _Synth_three_way { + _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty _FIRST_ARGUMENT_TYPE_NAME; + _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef _Ty _SECOND_ARGUMENT_TYPE_NAME; + + constexpr auto operator()(const _Ty& _Left, const _Ty& _Right) const { + if constexpr (three_way_comparable_with<_Ty, _Ty>) { + return _Left <=> _Right; + } else { + if (_Left < _Right) { + return weak_ordering::less; + } else if (_Right < _Left) { + return weak_ordering::greater; + } else { + return weak_ordering::equivalent; + } + } + } +}; + +// STRUCT TEMPLATE SPECIALIZATION _Synth_three_way +template <> +struct _Synth_three_way { + // clang-format off + template + constexpr auto operator()(_Ty1& _Left, _Ty2& _Right) const requires requires { + { _Left < _Right } ->_Boolean_testable; + { _Right < _Left } ->_Boolean_testable; + } + // clang-format on + { + if constexpr (three_way_comparable_with<_Ty1, _Ty2>) { + return _Left <=> _Right; + } else { + if (_Left < _Right) { + return weak_ordering::less; + } else if (_Right < _Left) { + return weak_ordering::greater; + } else { + return weak_ordering::equivalent; + } + } + } +}; + +// ALIAS TEMPLATE _Synth_three_way_result +template +using _Synth_three_way_result = decltype(_Synth_three_way{}(_STD declval<_Ty1&>(), _STD declval<_Ty2&>())); +#endif // defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts) + // FUNCTION TEMPLATE in_range template _NODISCARD constexpr _Ty _Min_limit() noexcept { // same as (numeric_limits<_Ty>::min)(), less throughput cost diff --git a/stl/inc/vector b/stl/inc/vector index 17902275c5..6531d43f9d 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -1766,6 +1766,7 @@ _NODISCARD bool operator==(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _ && _STD equal(_Left._Unchecked_begin(), _Left._Unchecked_end(), _Right._Unchecked_begin()); } +#if !_HAS_CXX20 || __cpp_impl_three_way_comparison < 201902L template _NODISCARD bool operator!=(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { return !(_Left == _Right); @@ -1791,6 +1792,16 @@ template _NODISCARD bool operator>=(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { return !(_Left < _Right); } +#endif // !_HAS_CXX20 || __cpp_impl_three_way_comparison < 201902L + +#if defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts) +template +_NODISCARD _Synth_three_way_result<_Ty> operator<=>( + const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { + return _STD lexicographical_compare_three_way( + _Left._Unchecked_begin(), _Left._Unchecked_end(), _Right._Unchecked_begin(), _Right._Unchecked_end()); +} +#endif // defined(__cpp_impl_three_way_comparison) && defined(__cpp_lib_concepts) // CLASS TEMPLATE vector AND FRIENDS using _Vbase = unsigned int; // word type for vector representation diff --git a/tests/std/test.lst b/tests/std/test.lst index 4c9d6bf510..e9f7a3fffd 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -234,6 +234,7 @@ tests\P0769R2_shift_left_shift_right tests\P0784R7_library_support_for_more_constexpr_containers tests\P0811R3_midpoint_lerp tests\P0896R4_P1614R2_comparisons +tests\P0896R4_P1614R2_spaceship tests\P0896R4_ranges_algorithm_machinery tests\P0896R4_ranges_alg_adjacent_find tests\P0896R4_ranges_alg_all_of diff --git a/tests/std/tests/P0896R4_P1614R2_spaceship/env.lst b/tests/std/tests/P0896R4_P1614R2_spaceship/env.lst new file mode 100644 index 0000000000..f3ccc8613c --- /dev/null +++ b/tests/std/tests/P0896R4_P1614R2_spaceship/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\concepts_matrix.lst diff --git a/tests/std/tests/P0896R4_P1614R2_spaceship/test.cpp b/tests/std/tests/P0896R4_P1614R2_spaceship/test.cpp new file mode 100644 index 0000000000..af64b57909 --- /dev/null +++ b/tests/std/tests/P0896R4_P1614R2_spaceship/test.cpp @@ -0,0 +1,193 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// Covers: +// * spaceship for containers + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +template +void ordered_containers_test(const Container& smaller, const Container& smaller_equal, const Container& larger) { + assert(smaller < larger); + assert(smaller <= larger); + assert(larger > smaller); + assert(larger >= smaller); + assert(smaller == smaller_equal); + assert(smaller != larger); + assert((smaller <=> larger) < 0); + assert((larger <=> smaller) > 0); + assert((smaller_equal <=> smaller) == 0); +} + +template +void unordered_containers_test(Container something, Container something_equal, Container different) { + assert(something == something_equal); + assert(something != different); +} + +void ordering_test_cases() { + { // constexpr array + constexpr std::array a0{{2, 8, 9, 1, 9}}; + constexpr std::array a1{{2, 8, 9}}; + constexpr std::array a2{{2, 8, 9, 1, 8}}; + + assert((a0 <=> a0) == 0); + assert((a1 <=> a1) == 0); + assert((a2 <=> a0) < 0); + assert((a0 <=> a2) > 0); + } + { + // array + std::array a1 = {100, 100, 100}; + std::array a2 = {100, 100, 100}; + std::array b1 = {200, 200}; + ordered_containers_test(a1, a2, b1); + } + { // deque + std::deque a1(3, 100); + std::deque a2(3, 100); + std::deque b1(2, 200); + ordered_containers_test(a1, a2, b1); + } + { // list + std::list a1(3, 100); + std::list a2(3, 100); + std::list b1(2, 200); + ordered_containers_test(a1, a2, b1); + } + { // vector + std::vector a1(3, 100); + std::vector a2(3, 100); + std::vector b1(2, 200); + ordered_containers_test(a1, a2, b1); + + std::vector c1(3, 0); + std::vector c2(3, 0); + std::vector d1(2, 1); + ordered_containers_test(c1, c2, d1); + } + { // 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); + } + { // map + std::map a1; + a1["hi"] = 1; + a1["hola"] = 2; + std::map a2; + a2["hi"] = 1; + a2["hola"] = 2; + std::map b1; + b1["zoe"] = 3; + b1["koala"] = 4; + ordered_containers_test(a1, a2, b1); + } + { // 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); + } + { // set + std::set a1; + a1.insert(10); + a1.insert(20); + + std::set a2; + a2.insert(10); + a2.insert(20); + + std::set b1; + b1.insert(30); + b1.insert(40); + ordered_containers_test(a1, a2, b1); + } + { // multiset + std::multiset a1; + a1.insert(10); + a1.insert(10); + a1.insert(20); + + std::multiset a2; + a2.insert(10); + a2.insert(20); + a2.insert(10); + + std::multiset b1; + b1.insert(30); + b1.insert(40); + b1.insert(40); + ordered_containers_test(a1, a2, b1); + } + { // unordered_map + using stringmap = std::unordered_map; + stringmap a = {{"cat", "tabby"}, {"dog", "poodle"}, {"bear", "grizzly"}}; + stringmap b = {{"dog", "poodle"}, {"bear", "grizzly"}, {"cat", "tabby"}}; + stringmap c = {{"cat", "siamese"}, {"dog", "lab"}, {"bear", "polar"}}; + unordered_containers_test(a, b, c); + } + { // unordered_multimap + using stringmap = std::unordered_multimap; + stringmap a = {{"cat", "tabby"}, {"dog", "poodle"}, {"cat", "siamese"}, {"dog", "poodle"}}; + 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_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_multiset + std::unordered_set a = {"cat", "dog", "cat"}; + std::unordered_set b = {"cat", "cat", "dog"}; + std::unordered_set c = {"mouse", "cat", "bear", "dog"}; + unordered_containers_test(a, b, c); + } + { // queue + std::deque deq1(3, 100); + std::deque deq2(2, 200); + std::queue a(deq1); + std::queue b(deq1); + std::queue c(deq2); + ordered_containers_test(a, b, c); + } + { // stack + std::stack a; + a.push(2); + a.push(2); + std::stack b; + b.push(2); + b.push(2); + std::stack c; + c.push(3); + c.push(3); + ordered_containers_test(a, b, c); + } +} + +int main() { + // STATIC_ASSERT((ordering_test_cases(), true)); + ordering_test_cases(); +}