mclow.lists updated this revision to Diff 136582. mclow.lists added a comment.
Add the `tuple` bits. Regularize the equality comparisons of the containers; i.e, don't try to be clever - let the compiler be clever. https://reviews.llvm.org/D43773 Files: include/array include/deque include/forward_list include/list include/tuple include/vector test/std/containers/sequences/array/compare.fail.cpp test/std/containers/sequences/array/compare.pass.cpp test/std/containers/sequences/deque/compare.fail.cpp test/std/containers/sequences/deque/compare.pass.cpp test/std/containers/sequences/forwardlist/compare.fail.cpp test/std/containers/sequences/forwardlist/compare.pass.cpp test/std/containers/sequences/list/compare.fail.cpp test/std/containers/sequences/list/compare.pass.cpp test/std/containers/sequences/vector/compare.fail.cpp test/std/containers/sequences/vector/compare.pass.cpp test/std/utilities/tuple/tuple.tuple/tuple.rel/eq.pass.cpp test/std/utilities/tuple/tuple.tuple/tuple.rel/lt.pass.cpp
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 <bool isLess, bool isEqual, typename T1, typename T2> +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<long, int, double> T1; + typedef std::tuple<double, long> 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<false, true >(t0, t0); + static_assert(!(t0 < t0), ""); + static_assert(!(t0 > t0), ""); + static_assert( (t0 <= t0), ""); + static_assert( (t0 >= t0), ""); + + compare<true, false>(t0, t1); + static_assert( (t0 < t1), ""); + static_assert(!(t0 > t1), ""); + static_assert( (t0 <= t1), ""); + static_assert(!(t0 >= t1), ""); + + compare<false, false>(t1, t0); + static_assert(!(t1 < t0), ""); + static_assert( (t1 > t0), ""); + static_assert(!(t1 <= t0), ""); + static_assert( (t1 >= t0), ""); + + compare<false, false>(t1, t2); + static_assert(!(t1 < t2), ""); + static_assert( (t1 > t2), ""); + static_assert(!(t1 <= t2), ""); + static_assert( (t1 >= t2), ""); + + compare<true, false>(t2, t1); + static_assert( (t2 < t1), ""); + static_assert(!(t2 > t1), ""); + static_assert( (t2 <= t1), ""); + static_assert(!(t2 >= t1), ""); + + compare<false, false>(t2, t3); + static_assert(!(t2 < t3), ""); + static_assert( (t2 > t3), ""); + static_assert(!(t2 <= t3), ""); + static_assert( (t2 >= t3), ""); + + compare<true, false>(t3, t2); + static_assert( (t3 < t2), ""); + static_assert(!(t3 > t2), ""); + static_assert( (t3 <= t2), ""); + static_assert(!(t3 >= t2), ""); + } #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<long, int, double> T1; + typedef std::tuple<double, long> 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/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. +// +//===----------------------------------------------------------------------===// + +// <vector> + +// template <class T, class Allocator> bool operator==(const vector<T,Allocator>& x, const vector<T,Allocator>& y); +// template <class T, class Allocator> bool operator< (const vector<T,Allocator>& x, const vector<T,Allocator>& y); +// template <class T, class Allocator> bool operator!=(const vector<T,Allocator>& x, const vector<T,Allocator>& y); +// template <class T, class Allocator> bool operator> (const vector<T,Allocator>& x, const vector<T,Allocator>& y); +// template <class T, class Allocator> bool operator>=(const vector<T,Allocator>& x, const vector<T,Allocator>& y); +// template <class T, class Allocator> bool operator<=(const vector<T,Allocator>& x, const vector<T,Allocator>& y); +// +// C++20 +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator==(const vector<T1, Allocator1>& x, const vector<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator< (const vector<T1, Allocator1>& x, const vector<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator!=(const vector<T1, Allocator1>& x, const vector<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator> (const vector<T1, Allocator1>& x, const vector<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator>=(const vector<T1, Allocator1>& x, const vector<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator<=(const vector<T1, Allocator1>& x, const vector<T2, Allocator2>& y); + + +#include <vector> +#include <cassert> + +#include "min_allocator.h" +#include "test_macros.h" + +template <class Vector> +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 <class Vector1, class Vector2> +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<T> 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<int> c0 = {}; + std::vector<int> c1 = {4}; + std::vector<long> c2 = {4L}; + std::vector<short> c3 = {2}; + std::vector<short, min_allocator<short>> 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. +// +//===----------------------------------------------------------------------===// + +// <vector> + +// template <class T, class Allocator> bool operator==(const vector<T,Allocator>& x, const vector<T,Allocator>& y); +// template <class T, class Allocator> bool operator< (const vector<T,Allocator>& x, const vector<T,Allocator>& y); +// template <class T, class Allocator> bool operator!=(const vector<T,Allocator>& x, const vector<T,Allocator>& y); +// template <class T, class Allocator> bool operator> (const vector<T,Allocator>& x, const vector<T,Allocator>& y); +// template <class T, class Allocator> bool operator>=(const vector<T,Allocator>& x, const vector<T,Allocator>& y); +// template <class T, class Allocator> bool operator<=(const vector<T,Allocator>& x, const vector<T,Allocator>& y); +// +// C++20 +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator==(const vector<T1, Allocator1>& x, const vector<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator< (const vector<T1, Allocator1>& x, const vector<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator!=(const vector<T1, Allocator1>& x, const vector<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator> (const vector<T1, Allocator1>& x, const vector<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator>=(const vector<T1, Allocator1>& x, const vector<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator<=(const vector<T1, Allocator1>& x, const vector<T2, Allocator2>& y); + + +#include <vector> +#include <string> +#include <cassert> + +#include "test_macros.h" + +template <int Dummy> struct NoCompare {}; + +int main() +{ + { + typedef NoCompare<0> T; + typedef std::vector<T> 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<T> 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<int> c1 = {}; + std::vector<std::string> 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. +// +//===----------------------------------------------------------------------===// + +// <list> + +// template <class T, class Allocator> bool operator==(const list<T,Allocator>& x, const list<T,Allocator>& y); +// template <class T, class Allocator> bool operator< (const list<T,Allocator>& x, const list<T,Allocator>& y); +// template <class T, class Allocator> bool operator!=(const list<T,Allocator>& x, const list<T,Allocator>& y); +// template <class T, class Allocator> bool operator> (const list<T,Allocator>& x, const list<T,Allocator>& y); +// template <class T, class Allocator> bool operator>=(const list<T,Allocator>& x, const list<T,Allocator>& y); +// template <class T, class Allocator> bool operator<=(const list<T,Allocator>& x, const list<T,Allocator>& y); +// +// C++20 +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator==(const list<T1, Allocator1>& x, const list<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator< (const list<T1, Allocator1>& x, const list<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator!=(const list<T1, Allocator1>& x, const list<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator> (const list<T1, Allocator1>& x, const list<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator>=(const list<T1, Allocator1>& x, const list<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator<=(const list<T1, Allocator1>& x, const list<T2, Allocator2>& y); + + +#include <list> +#include <cassert> + +#include "min_allocator.h" +#include "test_macros.h" + +template <class List> +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 <class List1, class List2> +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<T> 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<int> c0 = {}; + std::list<int> c1 = {4}; + std::list<long> c2 = {4L}; + std::list<short> c3 = {2}; + std::list<short, min_allocator<short>> 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. +// +//===----------------------------------------------------------------------===// + +// <list> + +// template <class T, class Allocator> bool operator==(const list<T,Allocator>& x, const list<T,Allocator>& y); +// template <class T, class Allocator> bool operator< (const list<T,Allocator>& x, const list<T,Allocator>& y); +// template <class T, class Allocator> bool operator!=(const list<T,Allocator>& x, const list<T,Allocator>& y); +// template <class T, class Allocator> bool operator> (const list<T,Allocator>& x, const list<T,Allocator>& y); +// template <class T, class Allocator> bool operator>=(const list<T,Allocator>& x, const list<T,Allocator>& y); +// template <class T, class Allocator> bool operator<=(const list<T,Allocator>& x, const list<T,Allocator>& y); +// +// C++20 +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator==(const list<T1, Allocator1>& x, const list<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator< (const list<T1, Allocator1>& x, const list<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator!=(const list<T1, Allocator1>& x, const list<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator> (const list<T1, Allocator1>& x, const list<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator>=(const list<T1, Allocator1>& x, const list<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator<=(const list<T1, Allocator1>& x, const list<T2, Allocator2>& y); + + +#include <list> +#include <string> +#include <cassert> + +#include "test_macros.h" + +template <int Dummy> struct NoCompare {}; + +int main() +{ + { + typedef NoCompare<0> T; + typedef std::list<T> 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<T> 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<int> c1 = {}; + std::list<std::string> 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. +// +//===----------------------------------------------------------------------===// + +// <forward_list> + +// template <class T, class Allocator> bool operator==(const forward_list<T,Allocator>& x, const forward_list<T,Allocator>& y); +// template <class T, class Allocator> bool operator< (const forward_list<T,Allocator>& x, const forward_list<T,Allocator>& y); +// template <class T, class Allocator> bool operator!=(const forward_list<T,Allocator>& x, const forward_list<T,Allocator>& y); +// template <class T, class Allocator> bool operator> (const forward_list<T,Allocator>& x, const forward_list<T,Allocator>& y); +// template <class T, class Allocator> bool operator>=(const forward_list<T,Allocator>& x, const forward_list<T,Allocator>& y); +// template <class T, class Allocator> bool operator<=(const forward_list<T,Allocator>& x, const forward_list<T,Allocator>& y); +// +// C++20 +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator==(const forward_list<T1, Allocator1>& x, const forward_list<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator< (const forward_list<T1, Allocator1>& x, const forward_list<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator!=(const forward_list<T1, Allocator1>& x, const forward_list<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator> (const forward_list<T1, Allocator1>& x, const forward_list<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator>=(const forward_list<T1, Allocator1>& x, const forward_list<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator<=(const forward_list<T1, Allocator1>& x, const forward_list<T2, Allocator2>& y); + + +#include <forward_list> +#include <cassert> + +#include "min_allocator.h" +#include "test_macros.h" + +template <class FList> +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 <class FList1, class FList2> +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<T> 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<int> c0 = {}; + std::forward_list<int> c1 = {4}; + std::forward_list<long> c2 = {4L}; + std::forward_list<short> c3 = {2}; + std::forward_list<short, min_allocator<short>> 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. +// +//===----------------------------------------------------------------------===// + +// <forward_list> + +// template <class T, class Allocator> bool operator==(const forward_list<T,Allocator>& x, const forward_list<T,Allocator>& y); +// template <class T, class Allocator> bool operator< (const forward_list<T,Allocator>& x, const forward_list<T,Allocator>& y); +// template <class T, class Allocator> bool operator!=(const forward_list<T,Allocator>& x, const forward_list<T,Allocator>& y); +// template <class T, class Allocator> bool operator> (const forward_list<T,Allocator>& x, const forward_list<T,Allocator>& y); +// template <class T, class Allocator> bool operator>=(const forward_list<T,Allocator>& x, const forward_list<T,Allocator>& y); +// template <class T, class Allocator> bool operator<=(const forward_list<T,Allocator>& x, const forward_list<T,Allocator>& y); +// +// C++20 +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator==(const forward_list<T1, Allocator1>& x, const forward_list<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator< (const forward_list<T1, Allocator1>& x, const forward_list<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator!=(const forward_list<T1, Allocator1>& x, const forward_list<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator> (const forward_list<T1, Allocator1>& x, const forward_list<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator>=(const forward_list<T1, Allocator1>& x, const forward_list<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator<=(const forward_list<T1, Allocator1>& x, const forward_list<T2, Allocator2>& y); + + +#include <forward_list> +#include <string> +#include <cassert> + +#include "test_macros.h" + +template <int Dummy> struct NoCompare {}; + +int main() +{ + { + typedef NoCompare<0> T; + typedef std::forward_list<T> 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<T> 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<int> c1 = {}; + std::forward_list<std::string> 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. +// +//===----------------------------------------------------------------------===// + +// <deque> + +// template <class T, class Allocator> bool operator==(const deque<T,Allocator>& x, const deque<T,Allocator>& y); +// template <class T, class Allocator> bool operator< (const deque<T,Allocator>& x, const deque<T,Allocator>& y); +// template <class T, class Allocator> bool operator!=(const deque<T,Allocator>& x, const deque<T,Allocator>& y); +// template <class T, class Allocator> bool operator> (const deque<T,Allocator>& x, const deque<T,Allocator>& y); +// template <class T, class Allocator> bool operator>=(const deque<T,Allocator>& x, const deque<T,Allocator>& y); +// template <class T, class Allocator> bool operator<=(const deque<T,Allocator>& x, const deque<T,Allocator>& y); +// +// C++20 +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator==(const deque<T1, Allocator1>& x, const deque<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator< (const deque<T1, Allocator1>& x, const deque<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator!=(const deque<T1, Allocator1>& x, const deque<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator> (const deque<T1, Allocator1>& x, const deque<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator>=(const deque<T1, Allocator1>& x, const deque<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator<=(const deque<T1, Allocator1>& x, const deque<T2, Allocator2>& y); + + +#include <deque> +#include <cassert> + +#include "min_allocator.h" +#include "test_macros.h" + +template <class Deque> +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 <class Deque1, class Deque2> +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<T> 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<int> c0 = {}; + std::deque<int> c1 = {4}; + std::deque<long> c2 = {4L}; + std::deque<short> c3 = {2}; + std::deque<short, min_allocator<short>> 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/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. +// +//===----------------------------------------------------------------------===// + +// <deque> + +// template <class T, class Allocator> bool operator==(const deque<T,Allocator>& x, const deque<T,Allocator>& y); +// template <class T, class Allocator> bool operator< (const deque<T,Allocator>& x, const deque<T,Allocator>& y); +// template <class T, class Allocator> bool operator!=(const deque<T,Allocator>& x, const deque<T,Allocator>& y); +// template <class T, class Allocator> bool operator> (const deque<T,Allocator>& x, const deque<T,Allocator>& y); +// template <class T, class Allocator> bool operator>=(const deque<T,Allocator>& x, const deque<T,Allocator>& y); +// template <class T, class Allocator> bool operator<=(const deque<T,Allocator>& x, const deque<T,Allocator>& y); +// +// C++20 +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator==(const deque<T1, Allocator1>& x, const deque<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator< (const deque<T1, Allocator1>& x, const deque<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator!=(const deque<T1, Allocator1>& x, const deque<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator> (const deque<T1, Allocator1>& x, const deque<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator>=(const deque<T1, Allocator1>& x, const deque<T2, Allocator2>& y); +// template<class T1, class T2, class Allocator1, class Allocator2> +// bool operator<=(const deque<T1, Allocator1>& x, const deque<T2, Allocator2>& y); + + +#include <deque> +#include <string> +#include <cassert> + +#include "test_macros.h" + +template <int Dummy> struct NoCompare {}; + +int main() +{ + { + typedef NoCompare<0> T; + typedef std::deque<T> 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<T> 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<int> c1 = {}; + std::deque<std::string> 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<T, N> const&, array<T, N> const&); // bool operator>=(array<T, N> const&, array<T, N> const&); +// C++20 +// template <class T1, class T2, size_t N1, size_t N2> +// bool operator==(const array<T1,N1>& x, const array<T2,N2>& y); +// template <class T1, class T2, size_t N1, size_t N2> +// bool operator!=(const array<T1,N1>& x, const array<T2,N2>& y); +// template <class T1, class T2, size_t N1, size_t N2> +// bool operator<(const array<T1,N1>& x, const array<T2,N2>& y); +// template <class T1, class T2, size_t N1, size_t N2> +// bool operator>(const array<T1,N1>& x, const array<T2,N2>& y); +// template <class T1, class T2, size_t N1, size_t N2> +// bool operator<=(const array<T1,N1>& x, const array<T2,N2>& y); +// template <class T1, class T2, size_t N1, size_t N2> +// bool operator>=(const array<T1,N1>& x, const array<T2,N2>& y); + #include <array> -#include <vector> #include <cassert> #include "test_macros.h" @@ -28,18 +41,25 @@ #include "disable_missing_braces_warning.h" template <class Array> -void test_compare(const Array& LHS, const Array& RHS) { - typedef std::vector<typename Array::value_type> 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 <class Array1, class Array2> +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<T, 0> C; C c1 = {}; C c2 = {}; - test_compare(c1, c2); + test_compare(c1, c2, false, true); } + +#if TEST_STD_VER > 17 + { + std::array<int, 0> c0 = {{}}; + std::array<int, 1> c1 = {{4}}; + std::array<long, 1> c2 = {{4L}}; + std::array<short, 1> 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/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<T, N> const&, array<T, N> const&); // bool operator>=(array<T, N> const&, array<T, N> const&); +// C++20 +// template <class T1, class T2, size_t N1, size_t N2> +// bool operator==(const array<T1,N1>& x, const array<T2,N2>& y); +// template <class T1, class T2, size_t N1, size_t N2> +// bool operator!=(const array<T1,N1>& x, const array<T2,N2>& y); +// template <class T1, class T2, size_t N1, size_t N2> +// bool operator<(const array<T1,N1>& x, const array<T2,N2>& y); +// template <class T1, class T2, size_t N1, size_t N2> +// bool operator>(const array<T1,N1>& x, const array<T2,N2>& y); +// template <class T1, class T2, size_t N1, size_t N2> +// bool operator<=(const array<T1,N1>& x, const array<T2,N2>& y); +// template <class T1, class T2, size_t N1, size_t N2> +// bool operator>=(const array<T1,N1>& x, const array<T2,N2>& y); + #include <array> #include <vector> +#include <string> #include <cassert> #include "test_macros.h" @@ -27,19 +42,6 @@ // Disable the missing braces warning for this reason. #include "disable_missing_braces_warning.h" -template <class Array> -void test_compare(const Array& LHS, const Array& RHS) { - typedef std::vector<typename Array::value_type> 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 <int Dummy> 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<int, 0> c1 = {{}}; + std::array<std::string, 0> c2 = {{}}; + // expected-error@algorithm:* 3 {{invalid operands to binary expression}} + TEST_IGNORE_NODISCARD (c1 == c2); + TEST_IGNORE_NODISCARD (c1 < c2); + } +#endif } Index: include/vector =================================================================== --- include/vector +++ include/vector @@ -253,6 +253,20 @@ template <class T, class Allocator> bool operator>=(const vector<T,Allocator>& x, const vector<T,Allocator>& y); template <class T, class Allocator> bool operator<=(const vector<T,Allocator>& x, const vector<T,Allocator>& y); +// C++20 +template<class T1, class T2, class Allocator1, class Allocator2> + bool operator==(const vector<T1, Allocator1>& x, const vector<T2, Allocator2>& y); +template<class T1, class T2, class Allocator1, class Allocator2> + bool operator< (const vector<T1, Allocator1>& x, const vector<T2, Allocator2>& y); +template<class T1, class T2, class Allocator1, class Allocator2> + bool operator!=(const vector<T1, Allocator1>& x, const vector<T2, Allocator2>& y); +template<class T1, class T2, class Allocator1, class Allocator2> + bool operator> (const vector<T1, Allocator1>& x, const vector<T2, Allocator2>& y); +template<class T1, class T2, class Allocator1, class Allocator2> + bool operator>=(const vector<T1, Allocator1>& x, const vector<T2, Allocator2>& y); +template<class T1, class T2, class Allocator1, class Allocator2> + bool operator<=(const vector<T1, Allocator1>& x, const vector<T2, Allocator2>& y); + template <class T, class Allocator> void swap(vector<T,Allocator>& x, vector<T,Allocator>& y) noexcept(noexcept(x.swap(y))); @@ -3352,6 +3366,58 @@ return !(__y < __x); } +#if _LIBCPP_STD_VER > 17 +template <class _Tp1, class _Tp2, class _Allocator1, class _Allocator2> +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 <class _Tp1, class _Tp2, class _Allocator1, class _Allocator2> +inline _LIBCPP_INLINE_VISIBILITY +bool +operator!=(const vector<_Tp1, _Allocator1>& __x, const vector<_Tp2, _Allocator2>& __y) +{ + return !(__x == __y); +} + +template <class _Tp1, class _Tp2, class _Allocator1, class _Allocator2> +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 <class _Tp1, class _Tp2, class _Allocator1, class _Allocator2> +inline _LIBCPP_INLINE_VISIBILITY +bool +operator> (const vector<_Tp1, _Allocator1>& __x, const vector<_Tp2, _Allocator2>& __y) +{ + return __y < __x; +} + +template <class _Tp1, class _Tp2, class _Allocator1, class _Allocator2> +inline _LIBCPP_INLINE_VISIBILITY +bool +operator>=(const vector<_Tp1, _Allocator1>& __x, const vector<_Tp2, _Allocator2>& __y) +{ + return !(__x < __y); +} + +template <class _Tp1, class _Tp2, class _Allocator1, class _Allocator2> +inline _LIBCPP_INLINE_VISIBILITY +bool +operator<=(const vector<_Tp1, _Allocator1>& __x, const vector<_Tp2, _Allocator2>& __y) +{ + return !(__y < __x); +} +#endif + template <class _Tp, class _Allocator> inline _LIBCPP_INLINE_VISIBILITY void Index: include/tuple =================================================================== --- include/tuple +++ include/tuple @@ -1111,6 +1111,10 @@ return tuple<_Tp&&...>(_VSTD::forward<_Tp>(__t)...); } +template <typename T> +_LIBCPP_CONSTEXPR _LIBCPP_ALWAYS_INLINE +const T& __min(const T& __x, const T& __y) { return __y < __x ? __y : __x; } + template <size_t _Ip> 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<sizeof...(_Tp)>()(__x, __y); + if (sizeof...(_Tp) != sizeof...(_Up)) + return false; + return __tuple_equal<__min(sizeof...(_Tp), sizeof...(_Up))>()(__x, __y); } template <class ..._Tp, class ..._Up> @@ -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<sizeof...(_Tp)>()(__x, __y); + return __tuple_less<__min(sizeof...(_Tp), sizeof...(_Up))>()(__x, __y); } template <class ..._Tp, class ..._Up> Index: include/list =================================================================== --- include/list +++ include/list @@ -160,6 +160,20 @@ template <class T, class Alloc> bool operator<=(const list<T,Alloc>& x, const list<T,Alloc>& y); +// C++20 +template<class T1, class T2, class Allocator1, class Allocator2> + bool operator==(const list<T1, Allocator1>& x, const list<T2, Allocator2>& y); +template<class T1, class T2, class Allocator1, class Allocator2> + bool operator< (const list<T1, Allocator1>& x, const list<T2, Allocator2>& y); +template<class T1, class T2, class Allocator1, class Allocator2> + bool operator!=(const list<T1, Allocator1>& x, const list<T2, Allocator2>& y); +template<class T1, class T2, class Allocator1, class Allocator2> + bool operator> (const list<T1, Allocator1>& x, const list<T2, Allocator2>& y); +template<class T1, class T2, class Allocator1, class Allocator2> + bool operator>=(const list<T1, Allocator1>& x, const list<T2, Allocator2>& y); +template<class T1, class T2, class Allocator1, class Allocator2> + bool operator<=(const list<T1, Allocator1>& x, const list<T2, Allocator2>& y); + template <class T, class Alloc> void swap(list<T,Alloc>& x, list<T,Alloc>& y) noexcept(noexcept(x.swap(y))); @@ -2405,6 +2419,58 @@ return !(__y < __x); } +#if _LIBCPP_STD_VER > 17 +template <class _Tp1, class _Tp2, class _Allocator1, class _Allocator2> +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 <class _Tp1, class _Tp2, class _Allocator1, class _Allocator2> +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 <class _Tp1, class _Tp2, class _Allocator1, class _Allocator2> +inline _LIBCPP_INLINE_VISIBILITY +bool +operator!=(const list<_Tp1, _Allocator1>& __x, const list<_Tp2, _Allocator2>& __y) +{ + return !(__x == __y); +} + +template <class _Tp1, class _Tp2, class _Allocator1, class _Allocator2> +inline _LIBCPP_INLINE_VISIBILITY +bool +operator> (const list<_Tp1, _Allocator1>& __x, const list<_Tp2, _Allocator2>& __y) +{ + return __y < __x; +} + +template <class _Tp1, class _Tp2, class _Allocator1, class _Allocator2> +inline _LIBCPP_INLINE_VISIBILITY +bool +operator>=(const list<_Tp1, _Allocator1>& __x, const list<_Tp2, _Allocator2>& __y) +{ + return !(__x < __y); +} + +template <class _Tp1, class _Tp2, class _Allocator1, class _Allocator2> +inline _LIBCPP_INLINE_VISIBILITY +bool +operator<=(const list<_Tp1, _Allocator1>& __x, const list<_Tp2, _Allocator2>& __y) +{ + return !(__y < __x); +} +#endif + template <class _Tp, class _Alloc> inline _LIBCPP_INLINE_VISIBILITY void Index: include/forward_list =================================================================== --- include/forward_list +++ include/forward_list @@ -158,6 +158,20 @@ bool operator<=(const forward_list<T, Allocator>& x, const forward_list<T, Allocator>& y); +// C++20 +template<class T1, class T2, class Allocator1, class Allocator2> + bool operator==(const forward_list<T1, Allocator1>& x, const forward_list<T2, Allocator2>& y); +template<class T1, class T2, class Allocator1, class Allocator2> + bool operator< (const forward_list<T1, Allocator1>& x, const forward_list<T2, Allocator2>& y); +template<class T1, class T2, class Allocator1, class Allocator2> + bool operator!=(const forward_list<T1, Allocator1>& x, const forward_list<T2, Allocator2>& y); +template<class T1, class T2, class Allocator1, class Allocator2> + bool operator> (const forward_list<T1, Allocator1>& x, const forward_list<T2, Allocator2>& y); +template<class T1, class T2, class Allocator1, class Allocator2> + bool operator>=(const forward_list<T1, Allocator1>& x, const forward_list<T2, Allocator2>& y); +template<class T1, class T2, class Allocator1, class Allocator2> + bool operator<=(const forward_list<T1, Allocator1>& x, const forward_list<T2, Allocator2>& y); + template <class T, class Allocator> void swap(forward_list<T, Allocator>& x, forward_list<T, Allocator>& y) noexcept(noexcept(x.swap(y))); @@ -1709,6 +1723,54 @@ return !(__y < __x); } +#if _LIBCPP_STD_VER > 17 +template <class _Tp1, class _Tp2, class _Allocator1, class _Allocator2> +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 <class _Tp1, class _Tp2, class _Allocator1, class _Allocator2> +bool operator!=(const forward_list<_Tp1, _Allocator1>& __x, + const forward_list<_Tp2, _Allocator2>& __y) +{ + return !(__x == __y); +} + +template <class _Tp1, class _Tp2, class _Allocator1, class _Allocator2> +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 <class _Tp1, class _Tp2, class _Allocator1, class _Allocator2> +inline _LIBCPP_INLINE_VISIBILITY +bool operator> (const forward_list<_Tp1, _Allocator1>& __x, + const forward_list<_Tp2, _Allocator2>& __y) +{ + return __y < __x; +} + +template <class _Tp1, class _Tp2, class _Allocator1, class _Allocator2> +inline _LIBCPP_INLINE_VISIBILITY +bool operator>=(const forward_list<_Tp1, _Allocator1>& __x, + const forward_list<_Tp2, _Allocator2>& __y) +{ + return !(__x < __y); +} + +template <class _Tp1, class _Tp2, class _Allocator1, class _Allocator2> +inline _LIBCPP_INLINE_VISIBILITY +bool operator<=(const forward_list<_Tp1, _Allocator1>& __x, + const forward_list<_Tp2, _Allocator2>& __y) +{ + return !(__y < __x); +} +#endif + template <class _Tp, class _Alloc> inline _LIBCPP_INLINE_VISIBILITY void Index: include/deque =================================================================== --- include/deque +++ include/deque @@ -141,6 +141,20 @@ template <class T, class Allocator> bool operator<=(const deque<T,Allocator>& x, const deque<T,Allocator>& y); +// C++20 +template<class T1, class T2, class Allocator1, class Allocator2> + bool operator==(const deque<T1, Allocator1>& x, const deque<T2, Allocator2>& y); +template<class T1, class T2, class Allocator1, class Allocator2> + bool operator< (const deque<T1, Allocator1>& x, const deque<T2, Allocator2>& y); +template<class T1, class T2, class Allocator1, class Allocator2> + bool operator!=(const deque<T1, Allocator1>& x, const deque<T2, Allocator2>& y); +template<class T1, class T2, class Allocator1, class Allocator2> + bool operator> (const deque<T1, Allocator1>& x, const deque<T2, Allocator2>& y); +template<class T1, class T2, class Allocator1, class Allocator2> + bool operator>=(const deque<T1, Allocator1>& x, const deque<T2, Allocator2>& y); +template<class T1, class T2, class Allocator1, class Allocator2> + bool operator<=(const deque<T1, Allocator1>& x, const deque<T2, Allocator2>& y); + // specialized algorithms: template <class T, class Allocator> void swap(deque<T,Allocator>& x, deque<T,Allocator>& y) @@ -2894,6 +2908,58 @@ return !(__y < __x); } +#if _LIBCPP_STD_VER > 17 +template <class _Tp1, class _Tp2, class _Allocator1, class _Allocator2> +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 <class _Tp1, class _Tp2, class _Allocator1, class _Allocator2> +inline _LIBCPP_INLINE_VISIBILITY +bool +operator!=(const deque<_Tp1, _Allocator1>& __x, const deque<_Tp2, _Allocator2>& __y) +{ + return !(__x == __y); +} + +template <class _Tp1, class _Tp2, class _Allocator1, class _Allocator2> +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 <class _Tp1, class _Tp2, class _Allocator1, class _Allocator2> +inline _LIBCPP_INLINE_VISIBILITY +bool +operator> (const deque<_Tp1, _Allocator1>& __x, const deque<_Tp2, _Allocator2>& __y) +{ + return __y < __x; +} + +template <class _Tp1, class _Tp2, class _Allocator1, class _Allocator2> +inline _LIBCPP_INLINE_VISIBILITY +bool +operator>=(const deque<_Tp1, _Allocator1>& __x, const deque<_Tp2, _Allocator2>& __y) +{ + return !(__x < __y); +} + +template <class _Tp1, class _Tp2, class _Allocator1, class _Allocator2> +inline _LIBCPP_INLINE_VISIBILITY +bool +operator<=(const deque<_Tp1, _Allocator1>& __x, const deque<_Tp2, _Allocator2>& __y) +{ + return !(__y < __x); +} +#endif + template <class _Tp, class _Allocator> inline _LIBCPP_INLINE_VISIBILITY void Index: include/array =================================================================== --- include/array +++ include/array @@ -85,6 +85,20 @@ template <class T, size_t N> bool operator>=(const array<T,N>& x, const array<T,N>& y); +// C++20 +template <class T1, class T2, size_t N1, size_t N2> + bool operator==(const array<T1,N1>& x, const array<T2,N2>& y); +template <class T1, class T2, size_t N1, size_t N2> + bool operator!=(const array<T1,N1>& x, const array<T2,N2>& y); +template <class T1, class T2, size_t N1, size_t N2> + bool operator<(const array<T1,N1>& x, const array<T2,N2>& y); +template <class T1, class T2, size_t N1, size_t N2> + bool operator>(const array<T1,N1>& x, const array<T2,N2>& y); +template <class T1, class T2, size_t N1, size_t N2> + bool operator<=(const array<T1,N1>& x, const array<T2,N2>& y); +template <class T1, class T2, size_t N1, size_t N2> + bool operator>=(const array<T1,N1>& x, const array<T2,N2>& y); + template <class T, size_t N > void swap(array<T,N>& x, array<T,N>& y) noexcept(noexcept(x.swap(y))); @@ -403,6 +417,59 @@ return !(__x < __y); } +#if _LIBCPP_STD_VER > 17 +template <class _Tp1, class _Tp2, size_t _Size1, size_t _Size2> +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 <class _Tp1, class _Tp2, size_t _Size1, size_t _Size2> +inline _LIBCPP_INLINE_VISIBILITY +bool +operator!=(const array<_Tp1, _Size1>& __x, const array<_Tp2, _Size2>& __y) +{ + return !(__x == __y); +} + +template <class _Tp1, class _Tp2, size_t _Size1, size_t _Size2> +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 <class _Tp1, class _Tp2, size_t _Size1, size_t _Size2> +inline _LIBCPP_INLINE_VISIBILITY +bool +operator>(const array<_Tp1, _Size1>& __x, const array<_Tp2, _Size2>& __y) +{ + return __y < __x; +} + +template <class _Tp1, class _Tp2, size_t _Size1, size_t _Size2> +inline _LIBCPP_INLINE_VISIBILITY +bool +operator<=(const array<_Tp1, _Size1>& __x, const array<_Tp2, _Size2>& __y) +{ + return !(__y < __x); +} + +template <class _Tp1, class _Tp2, size_t _Size1, size_t _Size2> +inline _LIBCPP_INLINE_VISIBILITY +bool +operator>=(const array<_Tp1, _Size1>& __x, const array<_Tp2, _Size2>& __y) +{ + return !(__x < __y); +} +#endif + template <class _Tp, size_t _Size> inline _LIBCPP_INLINE_VISIBILITY typename enable_if
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits