Index: include/array =================================================================== --- include/array +++ include/array @@ -85,6 +85,20 @@ template bool operator>=(const array& x, const array& y); +// C++20 +template + bool operator==(const array& x, const array& y); +template + bool operator!=(const array& x, const array& y); +template + bool operator<(const array& x, const array& y); +template + bool operator>(const array& x, const array& y); +template + bool operator<=(const array& x, const array& y); +template + bool operator>=(const array& x, const array& y); + template void swap(array& x, array& y) noexcept(noexcept(x.swap(y))); @@ -403,6 +417,59 @@ return !(__x < __y); } +#if _LIBCPP_STD_VER > 17 +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator==(const array<_Tp1, _Size1>& __x, const array<_Tp2, _Size2>& __y) +{ + if (_Size1 != _Size2) + return false; + return _VSTD::equal(__x.begin(), __x.end(), __y.begin()); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator!=(const array<_Tp1, _Size1>& __x, const array<_Tp2, _Size2>& __y) +{ + return !(__x == __y); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator<(const array<_Tp1, _Size1>& __x, const array<_Tp2, _Size2>& __y) +{ + return _VSTD::lexicographical_compare(__x.begin(), __x.end(), + __y.begin(), __y.end()); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator>(const array<_Tp1, _Size1>& __x, const array<_Tp2, _Size2>& __y) +{ + return __y < __x; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator<=(const array<_Tp1, _Size1>& __x, const array<_Tp2, _Size2>& __y) +{ + return !(__y < __x); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator>=(const array<_Tp1, _Size1>& __x, const array<_Tp2, _Size2>& __y) +{ + return !(__x < __y); +} +#endif + template inline _LIBCPP_INLINE_VISIBILITY typename enable_if Index: include/deque =================================================================== --- include/deque +++ include/deque @@ -141,6 +141,20 @@ template bool operator<=(const deque& x, const deque& y); +// C++20 +template + bool operator==(const deque& x, const deque& y); +template + bool operator< (const deque& x, const deque& y); +template + bool operator!=(const deque& x, const deque& y); +template + bool operator> (const deque& x, const deque& y); +template + bool operator>=(const deque& x, const deque& y); +template + bool operator<=(const deque& x, const deque& y); + // specialized algorithms: template void swap(deque& x, deque& y) @@ -2894,6 +2908,58 @@ return !(__y < __x); } +#if _LIBCPP_STD_VER > 17 +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator==(const deque<_Tp1, _Allocator1>& __x, const deque<_Tp2, _Allocator2>& __y) +{ + if (__x.size() != __y.size()) + return false; + return _VSTD::equal(__x.begin(), __x.end(), __y.begin()); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator!=(const deque<_Tp1, _Allocator1>& __x, const deque<_Tp2, _Allocator2>& __y) +{ + return !(__x == __y); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator< (const deque<_Tp1, _Allocator1>& __x, const deque<_Tp2, _Allocator2>& __y) +{ + return _VSTD::lexicographical_compare(__x.begin(), __x.end(), __y.begin(), __y.end()); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator> (const deque<_Tp1, _Allocator1>& __x, const deque<_Tp2, _Allocator2>& __y) +{ + return __y < __x; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator>=(const deque<_Tp1, _Allocator1>& __x, const deque<_Tp2, _Allocator2>& __y) +{ + return !(__x < __y); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator<=(const deque<_Tp1, _Allocator1>& __x, const deque<_Tp2, _Allocator2>& __y) +{ + return !(__y < __x); +} +#endif + template inline _LIBCPP_INLINE_VISIBILITY void Index: include/forward_list =================================================================== --- include/forward_list +++ include/forward_list @@ -158,6 +158,20 @@ bool operator<=(const forward_list& x, const forward_list& y); +// C++20 +template + bool operator==(const forward_list& x, const forward_list& y); +template + bool operator< (const forward_list& x, const forward_list& y); +template + bool operator!=(const forward_list& x, const forward_list& y); +template + bool operator> (const forward_list& x, const forward_list& y); +template + bool operator>=(const forward_list& x, const forward_list& y); +template + bool operator<=(const forward_list& x, const forward_list& y); + template void swap(forward_list& x, forward_list& y) noexcept(noexcept(x.swap(y))); @@ -1709,6 +1723,54 @@ return !(__y < __x); } +#if _LIBCPP_STD_VER > 17 +template +bool operator==(const forward_list<_Tp1, _Allocator1>& __x, + const forward_list<_Tp2, _Allocator2>& __y) +{ + return std::equal(__x.begin(), __x.end(), __y.begin(), __y.end()); +} + +template +bool operator!=(const forward_list<_Tp1, _Allocator1>& __x, + const forward_list<_Tp2, _Allocator2>& __y) +{ + return !(__x == __y); +} + +template +bool operator< (const forward_list<_Tp1, _Allocator1>& __x, + const forward_list<_Tp2, _Allocator2>& __y) +{ + return _VSTD::lexicographical_compare(__x.begin(), __x.end(), + __y.begin(), __y.end()); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool operator> (const forward_list<_Tp1, _Allocator1>& __x, + const forward_list<_Tp2, _Allocator2>& __y) +{ + return __y < __x; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool operator>=(const forward_list<_Tp1, _Allocator1>& __x, + const forward_list<_Tp2, _Allocator2>& __y) +{ + return !(__x < __y); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool operator<=(const forward_list<_Tp1, _Allocator1>& __x, + const forward_list<_Tp2, _Allocator2>& __y) +{ + return !(__y < __x); +} +#endif + template inline _LIBCPP_INLINE_VISIBILITY void Index: include/list =================================================================== --- include/list +++ include/list @@ -160,6 +160,20 @@ template bool operator<=(const list& x, const list& y); +// C++20 +template + bool operator==(const list& x, const list& y); +template + bool operator< (const list& x, const list& y); +template + bool operator!=(const list& x, const list& y); +template + bool operator> (const list& x, const list& y); +template + bool operator>=(const list& x, const list& y); +template + bool operator<=(const list& x, const list& y); + template void swap(list& x, list& y) noexcept(noexcept(x.swap(y))); @@ -2405,6 +2419,58 @@ return !(__y < __x); } +#if _LIBCPP_STD_VER > 17 +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator==(const list<_Tp1, _Allocator1>& __x, const list<_Tp2, _Allocator2>& __y) +{ + if (__x.size() != __y.size()) + return false; + return _VSTD::equal(__x.begin(), __x.end(), __y.begin()); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator< (const list<_Tp1, _Allocator1>& __x, const list<_Tp2, _Allocator2>& __y) +{ + return _VSTD::lexicographical_compare(__x.begin(), __x.end(), __y.begin(), __y.end()); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator!=(const list<_Tp1, _Allocator1>& __x, const list<_Tp2, _Allocator2>& __y) +{ + return !(__x == __y); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator> (const list<_Tp1, _Allocator1>& __x, const list<_Tp2, _Allocator2>& __y) +{ + return __y < __x; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator>=(const list<_Tp1, _Allocator1>& __x, const list<_Tp2, _Allocator2>& __y) +{ + return !(__x < __y); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator<=(const list<_Tp1, _Allocator1>& __x, const list<_Tp2, _Allocator2>& __y) +{ + return !(__y < __x); +} +#endif + template inline _LIBCPP_INLINE_VISIBILITY void Index: include/tuple =================================================================== --- include/tuple +++ include/tuple @@ -1111,6 +1111,10 @@ return tuple<_Tp&&...>(_VSTD::forward<_Tp>(__t)...); } +template +_LIBCPP_CONSTEXPR _LIBCPP_ALWAYS_INLINE +const T& __min(const T& __x, const T& __y) { return __y < __x ? __y : __x; } + template struct __tuple_equal { @@ -1129,7 +1133,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator()(const _Tp&, const _Up&) { - return true; + return tuple_size<_Tp>::value == tuple_size<_Up>::value; } }; @@ -1138,7 +1142,9 @@ bool operator==(const tuple<_Tp...>& __x, const tuple<_Up...>& __y) { - return __tuple_equal()(__x, __y); + if (sizeof...(_Tp) != sizeof...(_Up)) + return false; + return __tuple_equal<__min(sizeof...(_Tp), sizeof...(_Up))>()(__x, __y); } template @@ -1156,7 +1162,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator()(const _Tp& __x, const _Up& __y) { - const size_t __idx = tuple_size<_Tp>::value - _Ip; + const size_t __idx = __min(tuple_size<_Tp>::value, tuple_size<_Up>::value) - _Ip; if (_VSTD::get<__idx>(__x) < _VSTD::get<__idx>(__y)) return true; if (_VSTD::get<__idx>(__y) < _VSTD::get<__idx>(__x)) @@ -1172,7 +1178,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 bool operator()(const _Tp&, const _Up&) { - return false; + return tuple_size<_Tp>::value < tuple_size<_Up>::value; } }; @@ -1181,7 +1187,7 @@ bool operator<(const tuple<_Tp...>& __x, const tuple<_Up...>& __y) { - return __tuple_less()(__x, __y); + return __tuple_less<__min(sizeof...(_Tp), sizeof...(_Up))>()(__x, __y); } template Index: include/vector =================================================================== --- include/vector +++ include/vector @@ -253,6 +253,20 @@ template bool operator>=(const vector& x, const vector& y); template bool operator<=(const vector& x, const vector& y); +// C++20 +template + bool operator==(const vector& x, const vector& y); +template + bool operator< (const vector& x, const vector& y); +template + bool operator!=(const vector& x, const vector& y); +template + bool operator> (const vector& x, const vector& y); +template + bool operator>=(const vector& x, const vector& y); +template + bool operator<=(const vector& x, const vector& y); + template void swap(vector& x, vector& y) noexcept(noexcept(x.swap(y))); @@ -3352,6 +3366,58 @@ return !(__y < __x); } +#if _LIBCPP_STD_VER > 17 +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator==(const vector<_Tp1, _Allocator1>& __x, const vector<_Tp2, _Allocator2>& __y) +{ + if (__x.size() != __y.size()) + return false; + return _VSTD::equal(__x.begin(), __x.end(), __y.begin()); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator!=(const vector<_Tp1, _Allocator1>& __x, const vector<_Tp2, _Allocator2>& __y) +{ + return !(__x == __y); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator< (const vector<_Tp1, _Allocator1>& __x, const vector<_Tp2, _Allocator2>& __y) +{ + return _VSTD::lexicographical_compare(__x.begin(), __x.end(), __y.begin(), __y.end()); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator> (const vector<_Tp1, _Allocator1>& __x, const vector<_Tp2, _Allocator2>& __y) +{ + return __y < __x; +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator>=(const vector<_Tp1, _Allocator1>& __x, const vector<_Tp2, _Allocator2>& __y) +{ + return !(__x < __y); +} + +template +inline _LIBCPP_INLINE_VISIBILITY +bool +operator<=(const vector<_Tp1, _Allocator1>& __x, const vector<_Tp2, _Allocator2>& __y) +{ + return !(__y < __x); +} +#endif + template inline _LIBCPP_INLINE_VISIBILITY void Index: test/std/containers/sequences/array/compare.fail.cpp =================================================================== --- test/std/containers/sequences/array/compare.fail.cpp +++ test/std/containers/sequences/array/compare.fail.cpp @@ -16,9 +16,24 @@ // bool operator>(array const&, array const&); // bool operator>=(array const&, array const&); +// C++20 +// template +// bool operator==(const array& x, const array& y); +// template +// bool operator!=(const array& x, const array& y); +// template +// bool operator<(const array& x, const array& y); +// template +// bool operator>(const array& x, const array& y); +// template +// bool operator<=(const array& x, const array& y); +// template +// bool operator>=(const array& x, const array& y); + #include #include +#include #include #include "test_macros.h" @@ -27,19 +42,6 @@ // Disable the missing braces warning for this reason. #include "disable_missing_braces_warning.h" -template -void test_compare(const Array& LHS, const Array& RHS) { - typedef std::vector Vector; - const Vector LHSV(LHS.begin(), LHS.end()); - const Vector RHSV(RHS.begin(), RHS.end()); - assert((LHS == RHS) == (LHSV == RHSV)); - assert((LHS != RHS) == (LHSV != RHSV)); - assert((LHS < RHS) == (LHSV < RHSV)); - assert((LHS <= RHS) == (LHSV <= RHSV)); - assert((LHS > RHS) == (LHSV > RHSV)); - assert((LHS >= RHS) == (LHSV >= RHSV)); -} - template struct NoCompare {}; int main() @@ -68,4 +70,13 @@ TEST_IGNORE_NODISCARD (c1 == c1); TEST_IGNORE_NODISCARD (c1 < c1); } +#if TEST_STD_VER > 17 + { + std::array c1 = {{}}; + std::array c2 = {{}}; + // expected-error@algorithm:* 3 {{invalid operands to binary expression}} + TEST_IGNORE_NODISCARD (c1 == c2); + TEST_IGNORE_NODISCARD (c1 < c2); + } +#endif } Index: test/std/containers/sequences/array/compare.pass.cpp =================================================================== --- test/std/containers/sequences/array/compare.pass.cpp +++ test/std/containers/sequences/array/compare.pass.cpp @@ -16,9 +16,22 @@ // bool operator>(array const&, array const&); // bool operator>=(array const&, array const&); +// C++20 +// template +// bool operator==(const array& x, const array& y); +// template +// bool operator!=(const array& x, const array& y); +// template +// bool operator<(const array& x, const array& y); +// template +// bool operator>(const array& x, const array& y); +// template +// bool operator<=(const array& x, const array& y); +// template +// bool operator>=(const array& x, const array& y); + #include -#include #include #include "test_macros.h" @@ -28,18 +41,25 @@ #include "disable_missing_braces_warning.h" template -void test_compare(const Array& LHS, const Array& RHS) { - typedef std::vector Vector; - const Vector LHSV(LHS.begin(), LHS.end()); - const Vector RHSV(RHS.begin(), RHS.end()); - assert((LHS == RHS) == (LHSV == RHSV)); - assert((LHS != RHS) == (LHSV != RHSV)); - assert((LHS < RHS) == (LHSV < RHSV)); - assert((LHS <= RHS) == (LHSV <= RHSV)); - assert((LHS > RHS) == (LHSV > RHSV)); - assert((LHS >= RHS) == (LHSV >= RHSV)); +void test_compare(const Array& LHS, const Array& RHS, bool isLess, bool isEqual) { + assert((LHS == RHS) == isEqual); + assert((LHS != RHS) == !isEqual); + assert((LHS < RHS) == isLess); + assert((LHS <= RHS) == (isLess | isEqual)); + assert((LHS > RHS) == !(isLess | isEqual)); + assert((LHS >= RHS) == !isLess); } +template +void test_compare(const Array1& LHS, const Array2& RHS, bool isLess, bool isEqual) { + assert((LHS == RHS) == isEqual); + assert((LHS != RHS) == !isEqual); + assert((LHS < RHS) == isLess); + assert((LHS <= RHS) == (isLess | isEqual)); + assert((LHS > RHS) == !(isLess | isEqual)); + assert((LHS >= RHS) == !isLess); +} + int main() { { @@ -49,9 +69,9 @@ C c2 = {1, 2, 3}; C c3 = {3, 2, 1}; C c4 = {1, 2, 1}; - test_compare(c1, c2); - test_compare(c1, c3); - test_compare(c1, c4); + test_compare(c1, c2, false, true); + test_compare(c1, c3, true, false); + test_compare(c1, c4, false, false); } { typedef int T; @@ -58,6 +78,19 @@ typedef std::array C; C c1 = {}; C c2 = {}; - test_compare(c1, c2); + test_compare(c1, c2, false, true); } + +#if TEST_STD_VER > 17 + { + std::array c0 = {{}}; + std::array c1 = {{4}}; + std::array c2 = {{4L}}; + std::array c3 = {{2u}}; + test_compare(c0, c1, true, false); // same type, different lengths + test_compare(c0, c2, true, false); // different type, different lengths + test_compare(c1, c2, false, true); // different types, same length, same values + test_compare(c1, c3, false, false); // different types, same length, different values + } +#endif } Index: test/std/containers/sequences/deque/compare.fail.cpp =================================================================== --- test/std/containers/sequences/deque/compare.fail.cpp +++ test/std/containers/sequences/deque/compare.fail.cpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// template bool operator==(const deque& x, const deque& y); +// template bool operator< (const deque& x, const deque& y); +// template bool operator!=(const deque& x, const deque& y); +// template bool operator> (const deque& x, const deque& y); +// template bool operator>=(const deque& x, const deque& y); +// template bool operator<=(const deque& x, const deque& y); +// +// C++20 +// template +// bool operator==(const deque& x, const deque& y); +// template +// bool operator< (const deque& x, const deque& y); +// template +// bool operator!=(const deque& x, const deque& y); +// template +// bool operator> (const deque& x, const deque& y); +// template +// bool operator>=(const deque& x, const deque& y); +// template +// bool operator<=(const deque& x, const deque& y); + + +#include +#include +#include + +#include "test_macros.h" + +template struct NoCompare {}; + +int main() +{ + { + typedef NoCompare<0> T; + typedef std::deque C; + C c1 = {}; + // expected-error@algorithm:* 2 {{invalid operands to binary expression}} + TEST_IGNORE_NODISCARD (c1 == c1); + TEST_IGNORE_NODISCARD (c1 < c1); + } + { + typedef NoCompare<1> T; + typedef std::deque C; + C c1 = {}; + // expected-error@algorithm:* 2 {{invalid operands to binary expression}} + TEST_IGNORE_NODISCARD (c1 != c1); + TEST_IGNORE_NODISCARD (c1 > c1); + } + +#if TEST_STD_VER > 17 + { + std::deque c1 = {}; + std::deque c2 = {}; + // expected-error@algorithm:* 3 {{invalid operands to binary expression}} + TEST_IGNORE_NODISCARD (c1 == c2); + TEST_IGNORE_NODISCARD (c1 < c2); + } +#endif +} Index: test/std/containers/sequences/deque/compare.pass.cpp =================================================================== --- test/std/containers/sequences/deque/compare.pass.cpp +++ test/std/containers/sequences/deque/compare.pass.cpp @@ -0,0 +1,90 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// template bool operator==(const deque& x, const deque& y); +// template bool operator< (const deque& x, const deque& y); +// template bool operator!=(const deque& x, const deque& y); +// template bool operator> (const deque& x, const deque& y); +// template bool operator>=(const deque& x, const deque& y); +// template bool operator<=(const deque& x, const deque& y); +// +// C++20 +// template +// bool operator==(const deque& x, const deque& y); +// template +// bool operator< (const deque& x, const deque& y); +// template +// bool operator!=(const deque& x, const deque& y); +// template +// bool operator> (const deque& x, const deque& y); +// template +// bool operator>=(const deque& x, const deque& y); +// template +// bool operator<=(const deque& x, const deque& y); + + +#include +#include + +#include "min_allocator.h" +#include "test_macros.h" + +template +void test_compare(const Deque& LHS, const Deque& RHS, bool isLess, bool isEqual) { + assert((LHS == RHS) == isEqual); + assert((LHS != RHS) == !isEqual); + assert((LHS < RHS) == isLess); + assert((LHS <= RHS) == (isLess | isEqual)); + assert((LHS > RHS) == !(isLess | isEqual)); + assert((LHS >= RHS) == !isLess); +} + +template +void test_compare(const Deque1& LHS, const Deque2& RHS, bool isLess, bool isEqual) { + assert((LHS == RHS) == isEqual); + assert((LHS != RHS) == !isEqual); + assert((LHS < RHS) == isLess); + assert((LHS <= RHS) == (isLess | isEqual)); + assert((LHS > RHS) == !(isLess | isEqual)); + assert((LHS >= RHS) == !isLess); +} + +int main() +{ + { + typedef int T; + typedef std::deque C; + C c0 = {}; + C c1 = {1, 2, 3}; + C c2 = {1, 2, 3}; + C c3 = {3, 2, 1}; + C c4 = {1, 2, 1}; + test_compare(c0, c1, true, false); + test_compare(c1, c2, false, true); + test_compare(c1, c3, true, false); + test_compare(c1, c4, false, false); + } + +#if TEST_STD_VER > 17 + { + std::deque c0 = {}; + std::deque c1 = {4}; + std::deque c2 = {4L}; + std::deque c3 = {2}; + std::deque> c4 = {4}; + test_compare(c0, c1, true, false); // same type, different lengths + test_compare(c0, c2, true, false); // different type, different lengths + test_compare(c1, c2, false, true); // different types, same length, same values + test_compare(c1, c3, false, false); // different types, same length, different values + test_compare(c1, c4, false, true); // different types, same length, same value, different allocator + } +#endif +} Index: test/std/containers/sequences/forwardlist/compare.fail.cpp =================================================================== --- test/std/containers/sequences/forwardlist/compare.fail.cpp +++ test/std/containers/sequences/forwardlist/compare.fail.cpp @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// template bool operator==(const forward_list& x, const forward_list& y); +// template bool operator< (const forward_list& x, const forward_list& y); +// template bool operator!=(const forward_list& x, const forward_list& y); +// template bool operator> (const forward_list& x, const forward_list& y); +// template bool operator>=(const forward_list& x, const forward_list& y); +// template bool operator<=(const forward_list& x, const forward_list& y); +// +// C++20 +// template +// bool operator==(const forward_list& x, const forward_list& y); +// template +// bool operator< (const forward_list& x, const forward_list& y); +// template +// bool operator!=(const forward_list& x, const forward_list& y); +// template +// bool operator> (const forward_list& x, const forward_list& y); +// template +// bool operator>=(const forward_list& x, const forward_list& y); +// template +// bool operator<=(const forward_list& x, const forward_list& y); + + +#include +#include +#include + +#include "test_macros.h" + +template struct NoCompare {}; + +int main() +{ + { + typedef NoCompare<0> T; + typedef std::forward_list C; + C c1 = {}; + // expected-error@algorithm:* {{invalid operands to binary expression}} + // expected-error@forward_list:* {{invalid operands to binary expression}} + TEST_IGNORE_NODISCARD (c1 == c1); + TEST_IGNORE_NODISCARD (c1 < c1); + } + { + typedef NoCompare<1> T; + typedef std::forward_list C; + C c1 = {}; + // expected-error@algorithm:* {{invalid operands to binary expression}} + // expected-error@forward_list:* {{invalid operands to binary expression}} + TEST_IGNORE_NODISCARD (c1 != c1); + TEST_IGNORE_NODISCARD (c1 > c1); + } + +#if TEST_STD_VER > 17 + { + std::forward_list c1 = {}; + std::forward_list c2 = {}; + // expected-error@algorithm:* 3 {{invalid operands to binary expression}} + TEST_IGNORE_NODISCARD (c1 == c2); + TEST_IGNORE_NODISCARD (c1 < c2); + } +#endif +} Index: test/std/containers/sequences/forwardlist/compare.pass.cpp =================================================================== --- test/std/containers/sequences/forwardlist/compare.pass.cpp +++ test/std/containers/sequences/forwardlist/compare.pass.cpp @@ -0,0 +1,90 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// template bool operator==(const forward_list& x, const forward_list& y); +// template bool operator< (const forward_list& x, const forward_list& y); +// template bool operator!=(const forward_list& x, const forward_list& y); +// template bool operator> (const forward_list& x, const forward_list& y); +// template bool operator>=(const forward_list& x, const forward_list& y); +// template bool operator<=(const forward_list& x, const forward_list& y); +// +// C++20 +// template +// bool operator==(const forward_list& x, const forward_list& y); +// template +// bool operator< (const forward_list& x, const forward_list& y); +// template +// bool operator!=(const forward_list& x, const forward_list& y); +// template +// bool operator> (const forward_list& x, const forward_list& y); +// template +// bool operator>=(const forward_list& x, const forward_list& y); +// template +// bool operator<=(const forward_list& x, const forward_list& y); + + +#include +#include + +#include "min_allocator.h" +#include "test_macros.h" + +template +void test_compare(const FList& LHS, const FList& RHS, bool isLess, bool isEqual) { + assert((LHS == RHS) == isEqual); + assert((LHS != RHS) == !isEqual); + assert((LHS < RHS) == isLess); + assert((LHS <= RHS) == (isLess | isEqual)); + assert((LHS > RHS) == !(isLess | isEqual)); + assert((LHS >= RHS) == !isLess); +} + +template +void test_compare(const FList1& LHS, const FList2& RHS, bool isLess, bool isEqual) { + assert((LHS == RHS) == isEqual); + assert((LHS != RHS) == !isEqual); + assert((LHS < RHS) == isLess); + assert((LHS <= RHS) == (isLess | isEqual)); + assert((LHS > RHS) == !(isLess | isEqual)); + assert((LHS >= RHS) == !isLess); +} + +int main() +{ + { + typedef int T; + typedef std::forward_list C; + C c0 = {}; + C c1 = {1, 2, 3}; + C c2 = {1, 2, 3}; + C c3 = {3, 2, 1}; + C c4 = {1, 2, 1}; + test_compare(c0, c1, true, false); + test_compare(c1, c2, false, true); + test_compare(c1, c3, true, false); + test_compare(c1, c4, false, false); + } + +#if TEST_STD_VER > 17 + { + std::forward_list c0 = {}; + std::forward_list c1 = {4}; + std::forward_list c2 = {4L}; + std::forward_list c3 = {2}; + std::forward_list> c4 = {4}; + test_compare(c0, c1, true, false); // same type, different lengths + test_compare(c0, c2, true, false); // different type, different lengths + test_compare(c1, c2, false, true); // different types, same length, same values + test_compare(c1, c3, false, false); // different types, same length, different values + test_compare(c1, c4, false, true); // different types, same length, same value, different allocator + } +#endif +} Index: test/std/containers/sequences/list/compare.fail.cpp =================================================================== --- test/std/containers/sequences/list/compare.fail.cpp +++ test/std/containers/sequences/list/compare.fail.cpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// template bool operator==(const list& x, const list& y); +// template bool operator< (const list& x, const list& y); +// template bool operator!=(const list& x, const list& y); +// template bool operator> (const list& x, const list& y); +// template bool operator>=(const list& x, const list& y); +// template bool operator<=(const list& x, const list& y); +// +// C++20 +// template +// bool operator==(const list& x, const list& y); +// template +// bool operator< (const list& x, const list& y); +// template +// bool operator!=(const list& x, const list& y); +// template +// bool operator> (const list& x, const list& y); +// template +// bool operator>=(const list& x, const list& y); +// template +// bool operator<=(const list& x, const list& y); + + +#include +#include +#include + +#include "test_macros.h" + +template struct NoCompare {}; + +int main() +{ + { + typedef NoCompare<0> T; + typedef std::list C; + C c1 = {}; + // expected-error@algorithm:* 2 {{invalid operands to binary expression}} + TEST_IGNORE_NODISCARD (c1 == c1); + TEST_IGNORE_NODISCARD (c1 < c1); + } + { + typedef NoCompare<1> T; + typedef std::list C; + C c1 = {}; + // expected-error@algorithm:* 2 {{invalid operands to binary expression}} + TEST_IGNORE_NODISCARD (c1 != c1); + TEST_IGNORE_NODISCARD (c1 > c1); + } + +#if TEST_STD_VER > 17 + { + std::list c1 = {}; + std::list c2 = {}; + // expected-error@algorithm:* 3 {{invalid operands to binary expression}} + TEST_IGNORE_NODISCARD (c1 == c2); + TEST_IGNORE_NODISCARD (c1 < c2); + } +#endif +} Index: test/std/containers/sequences/list/compare.pass.cpp =================================================================== --- test/std/containers/sequences/list/compare.pass.cpp +++ test/std/containers/sequences/list/compare.pass.cpp @@ -0,0 +1,90 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// template bool operator==(const list& x, const list& y); +// template bool operator< (const list& x, const list& y); +// template bool operator!=(const list& x, const list& y); +// template bool operator> (const list& x, const list& y); +// template bool operator>=(const list& x, const list& y); +// template bool operator<=(const list& x, const list& y); +// +// C++20 +// template +// bool operator==(const list& x, const list& y); +// template +// bool operator< (const list& x, const list& y); +// template +// bool operator!=(const list& x, const list& y); +// template +// bool operator> (const list& x, const list& y); +// template +// bool operator>=(const list& x, const list& y); +// template +// bool operator<=(const list& x, const list& y); + + +#include +#include + +#include "min_allocator.h" +#include "test_macros.h" + +template +void test_compare(const List& LHS, const List& RHS, bool isLess, bool isEqual) { + assert((LHS == RHS) == isEqual); + assert((LHS != RHS) == !isEqual); + assert((LHS < RHS) == isLess); + assert((LHS <= RHS) == (isLess | isEqual)); + assert((LHS > RHS) == !(isLess | isEqual)); + assert((LHS >= RHS) == !isLess); +} + +template +void test_compare(const List1& LHS, const List2& RHS, bool isLess, bool isEqual) { + assert((LHS == RHS) == isEqual); + assert((LHS != RHS) == !isEqual); + assert((LHS < RHS) == isLess); + assert((LHS <= RHS) == (isLess | isEqual)); + assert((LHS > RHS) == !(isLess | isEqual)); + assert((LHS >= RHS) == !isLess); +} + +int main() +{ + { + typedef int T; + typedef std::list C; + C c0 = {}; + C c1 = {1, 2, 3}; + C c2 = {1, 2, 3}; + C c3 = {3, 2, 1}; + C c4 = {1, 2, 1}; + test_compare(c0, c1, true, false); + test_compare(c1, c2, false, true); + test_compare(c1, c3, true, false); + test_compare(c1, c4, false, false); + } + +#if TEST_STD_VER > 17 + { + std::list c0 = {}; + std::list c1 = {4}; + std::list c2 = {4L}; + std::list c3 = {2}; + std::list> c4 = {4}; + test_compare(c0, c1, true, false); // same type, different lengths + test_compare(c0, c2, true, false); // different type, different lengths + test_compare(c1, c2, false, true); // different types, same length, same values + test_compare(c1, c3, false, false); // different types, same length, different values + test_compare(c1, c4, false, true); // different types, same length, same value, different allocator + } +#endif +} Index: test/std/containers/sequences/vector/compare.fail.cpp =================================================================== --- test/std/containers/sequences/vector/compare.fail.cpp +++ test/std/containers/sequences/vector/compare.fail.cpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// template bool operator==(const vector& x, const vector& y); +// template bool operator< (const vector& x, const vector& y); +// template bool operator!=(const vector& x, const vector& y); +// template bool operator> (const vector& x, const vector& y); +// template bool operator>=(const vector& x, const vector& y); +// template bool operator<=(const vector& x, const vector& y); +// +// C++20 +// template +// bool operator==(const vector& x, const vector& y); +// template +// bool operator< (const vector& x, const vector& y); +// template +// bool operator!=(const vector& x, const vector& y); +// template +// bool operator> (const vector& x, const vector& y); +// template +// bool operator>=(const vector& x, const vector& y); +// template +// bool operator<=(const vector& x, const vector& y); + + +#include +#include +#include + +#include "test_macros.h" + +template struct NoCompare {}; + +int main() +{ + { + typedef NoCompare<0> T; + typedef std::vector C; + C c1 = {}; + // expected-error@algorithm:* 2 {{invalid operands to binary expression}} + TEST_IGNORE_NODISCARD (c1 == c1); + TEST_IGNORE_NODISCARD (c1 < c1); + } + { + typedef NoCompare<1> T; + typedef std::vector C; + C c1 = {}; + // expected-error@algorithm:* 2 {{invalid operands to binary expression}} + TEST_IGNORE_NODISCARD (c1 != c1); + TEST_IGNORE_NODISCARD (c1 > c1); + } + +#if TEST_STD_VER > 17 + { + std::vector c1 = {}; + std::vector c2 = {}; + // expected-error@algorithm:* 3 {{invalid operands to binary expression}} + TEST_IGNORE_NODISCARD (c1 == c2); + TEST_IGNORE_NODISCARD (c1 < c2); + } +#endif +} Index: test/std/containers/sequences/vector/compare.pass.cpp =================================================================== --- test/std/containers/sequences/vector/compare.pass.cpp +++ test/std/containers/sequences/vector/compare.pass.cpp @@ -0,0 +1,90 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// template bool operator==(const vector& x, const vector& y); +// template bool operator< (const vector& x, const vector& y); +// template bool operator!=(const vector& x, const vector& y); +// template bool operator> (const vector& x, const vector& y); +// template bool operator>=(const vector& x, const vector& y); +// template bool operator<=(const vector& x, const vector& y); +// +// C++20 +// template +// bool operator==(const vector& x, const vector& y); +// template +// bool operator< (const vector& x, const vector& y); +// template +// bool operator!=(const vector& x, const vector& y); +// template +// bool operator> (const vector& x, const vector& y); +// template +// bool operator>=(const vector& x, const vector& y); +// template +// bool operator<=(const vector& x, const vector& y); + + +#include +#include + +#include "min_allocator.h" +#include "test_macros.h" + +template +void test_compare(const Vector& LHS, const Vector& RHS, bool isLess, bool isEqual) { + assert((LHS == RHS) == isEqual); + assert((LHS != RHS) == !isEqual); + assert((LHS < RHS) == isLess); + assert((LHS <= RHS) == (isLess | isEqual)); + assert((LHS > RHS) == !(isLess | isEqual)); + assert((LHS >= RHS) == !isLess); +} + +template +void test_compare(const Vector1& LHS, const Vector2& RHS, bool isLess, bool isEqual) { + assert((LHS == RHS) == isEqual); + assert((LHS != RHS) == !isEqual); + assert((LHS < RHS) == isLess); + assert((LHS <= RHS) == (isLess | isEqual)); + assert((LHS > RHS) == !(isLess | isEqual)); + assert((LHS >= RHS) == !isLess); +} + +int main() +{ + { + typedef int T; + typedef std::vector C; + C c0 = {}; + C c1 = {1, 2, 3}; + C c2 = {1, 2, 3}; + C c3 = {3, 2, 1}; + C c4 = {1, 2, 1}; + test_compare(c0, c1, true, false); + test_compare(c1, c2, false, true); + test_compare(c1, c3, true, false); + test_compare(c1, c4, false, false); + } + +#if TEST_STD_VER > 17 + { + std::vector c0 = {}; + std::vector c1 = {4}; + std::vector c2 = {4L}; + std::vector c3 = {2}; + std::vector> c4 = {4}; + test_compare(c0, c1, true, false); // same type, different lengths + test_compare(c0, c2, true, false); // different type, different lengths + test_compare(c1, c2, false, true); // different types, same length, same values + test_compare(c1, c3, false, false); // different types, same length, different values + test_compare(c1, c4, false, true); // different types, same length, same value, different allocator + } +#endif +} Index: test/std/utilities/tuple/tuple.tuple/tuple.rel/eq.pass.cpp =================================================================== --- test/std/utilities/tuple/tuple.tuple/tuple.rel/eq.pass.cpp +++ test/std/utilities/tuple/tuple.tuple/tuple.rel/eq.pass.cpp @@ -154,5 +154,20 @@ static_assert(!(t1 == t2), ""); static_assert(t1 != t2, ""); } + { // P0805 + typedef std::tuple T1; + typedef std::tuple T2; + constexpr T1 t1(1, 2, 3); + constexpr T2 t2(1.1, 3); + constexpr T2 t3(1, 2); + static_assert(!(t1 == t2), ""); + static_assert(!(t2 == t1), ""); + static_assert(!(t1 == t3), ""); + static_assert(!(t3 == t1), ""); + static_assert( t1 != t2, ""); + static_assert( t2 != t1, ""); + static_assert( t1 != t3, ""); + static_assert( t3 != t1, ""); + } #endif } Index: test/std/utilities/tuple/tuple.tuple/tuple.rel/lt.pass.cpp =================================================================== --- test/std/utilities/tuple/tuple.tuple/tuple.rel/lt.pass.cpp +++ test/std/utilities/tuple/tuple.tuple/tuple.rel/lt.pass.cpp @@ -35,6 +35,16 @@ #include "test_macros.h" + +template +void compare (const T1 &t1, const T2 &t2) +{ + assert((t1 < t2) == ( isLess)); + assert((t1 > t2) == (!isLess && !isEqual)); + assert((t1 <= t2) == ( isLess || isEqual)); + assert((t1 >= t2) == (!isLess || isEqual)); +} + int main() { { @@ -208,5 +218,57 @@ static_assert(!(t1 > t2), ""); static_assert(!(t1 >= t2), ""); } + { // P0805 + typedef std::tuple<> T0; + typedef std::tuple T1; + typedef std::tuple T2; + constexpr T0 t0; + constexpr T1 t1(1, 2, 3); + constexpr T2 t2(1, 2); + constexpr T1 t3(0, 1, 2); // common tail + + // less, equal + compare(t0, t0); + static_assert(!(t0 < t0), ""); + static_assert(!(t0 > t0), ""); + static_assert( (t0 <= t0), ""); + static_assert( (t0 >= t0), ""); + + compare(t0, t1); + static_assert( (t0 < t1), ""); + static_assert(!(t0 > t1), ""); + static_assert( (t0 <= t1), ""); + static_assert(!(t0 >= t1), ""); + + compare(t1, t0); + static_assert(!(t1 < t0), ""); + static_assert( (t1 > t0), ""); + static_assert(!(t1 <= t0), ""); + static_assert( (t1 >= t0), ""); + + compare(t1, t2); + static_assert(!(t1 < t2), ""); + static_assert( (t1 > t2), ""); + static_assert(!(t1 <= t2), ""); + static_assert( (t1 >= t2), ""); + + compare(t2, t1); + static_assert( (t2 < t1), ""); + static_assert(!(t2 > t1), ""); + static_assert( (t2 <= t1), ""); + static_assert(!(t2 >= t1), ""); + + compare(t2, t3); + static_assert(!(t2 < t3), ""); + static_assert( (t2 > t3), ""); + static_assert(!(t2 <= t3), ""); + static_assert( (t2 >= t3), ""); + + compare(t3, t2); + static_assert( (t3 < t2), ""); + static_assert(!(t3 > t2), ""); + static_assert( (t3 <= t2), ""); + static_assert(!(t3 >= t2), ""); + } #endif }