mclow.lists created this revision.
mclow.lists added a reviewer: EricWF.

P0805R1 <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0805r1.html> 
is about comparing heterogenous containers.

This is the implementation for `array`, `vector`, `deque`, `list` and 
`forward_list`.
The `tuple` bits will follow soon.

I hope to land this immediately after it is adopted in Jacksonville.


https://reviews.llvm.org/D43773

Files:
  include/array
  include/deque
  include/list
  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

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"
@@ -68,4 +83,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,57 @@
     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)
+{
+    const typename vector<_Tp1, _Allocator1>::size_type __sz = __x.size();
+    return __sz == __y.size() && _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/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,56 @@
     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)
+{
+    return __x.size() == __y.size() && _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/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,57 @@
     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)
+{
+    const typename deque<_Tp1, _Allocator1>::size_type __sz = __x.size();
+    return __sz == __y.size() && _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(), __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 !(__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

Reply via email to