[libcxx-commits] [libcxx] 55ec808 - [libc++][spaceship] Implement `operator<=>` for `vector`

Hristo Hristov via libcxx-commits libcxx-commits at lists.llvm.org
Fri Jun 9 20:53:11 PDT 2023


Author: Hristo Hristov
Date: 2023-06-10T06:53:05+03:00
New Revision: 55ec808a889726e0547b7e2f0aa12bc197f6d163

URL: https://github.com/llvm/llvm-project/commit/55ec808a889726e0547b7e2f0aa12bc197f6d163
DIFF: https://github.com/llvm/llvm-project/commit/55ec808a889726e0547b7e2f0aa12bc197f6d163.diff

LOG: [libc++][spaceship] Implement `operator<=>` for `vector`

Implements part of P1614R2 "The Mothership has Landed"

Depends on D150188

Reviewed By: Mordante, #libc

Differential Revision: https://reviews.llvm.org/D132268

Added: 
    libcxx/test/std/containers/sequences/vector.bool/compare.three_way.pass.cpp
    libcxx/test/std/containers/sequences/vector/compare.three_way.pass.cpp

Modified: 
    libcxx/docs/Status/SpaceshipProjects.csv
    libcxx/include/vector

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/Status/SpaceshipProjects.csv b/libcxx/docs/Status/SpaceshipProjects.csv
index e912983a1bfdf..d118db07edff9 100644
--- a/libcxx/docs/Status/SpaceshipProjects.csv
+++ b/libcxx/docs/Status/SpaceshipProjects.csv
@@ -40,7 +40,8 @@ Section,Description,Dependencies,Assignee,Complete
 | `[deque.syn] <https://wg21.link/deque.syn>`_ (`general <https://wg21.link/container.opt.reqmts>`_),| `deque <https://reviews.llvm.org/D144821>`_,[expos.only.func],Hristo Hristov,|Complete|
 | `[forward.list.syn] <https://wg21.link/forward.list.syn>`_ (`general <https://wg21.link/container.opt.reqmts>`_),| `forward_list <https://reviews.llvm.org/D145172>`_,[expos.only.func],Hristo Hristov,|Complete|
 | `[list.syn] <https://wg21.link/list.syn>`_ (`general <https://wg21.link/container.opt.reqmts>`_),| `list <https://reviews.llvm.org/D132312>`_,[expos.only.func],Adrian Vogelsgesang,|Complete|
-| `[vector.syn] <https://wg21.link/vector.syn>`_ (`general <https://wg21.link/container.opt.reqmts>`_),| `vector <https://reviews.llvm.org/D132268>`_,[expos.only.func],Adrian Vogelsgesang,|In Progress|
+| `[vector.syn] <https://wg21.link/vector.syn>`_ (`general <https://wg21.link/container.opt.reqmts>`_),| `vector <https://reviews.llvm.org/D132268>`_,[expos.only.func],"| Adrian Vogelsgesang
+| Hristo Hristov",|Complete|
 | `[associative.map.syn] <https://wg21.link/associative.map.syn>`_ (`general <https://wg21.link/container.opt.reqmts>`_),"| `map <https://reviews.llvm.org/D145976>`_
 | `multimap <https://reviews.llvm.org/D145976>`_",[expos.only.func],Hristo Hristov,|Complete|
 | `[associative.set.syn] <https://wg21.link/associative.set.syn>`_ (`general <https://wg21.link/container.opt.reqmts>`_),"| multiset

diff  --git a/libcxx/include/vector b/libcxx/include/vector
index 82078fbb248ad..33db49a099d40 100644
--- a/libcxx/include/vector
+++ b/libcxx/include/vector
@@ -269,12 +269,15 @@ template<ranges::input_range R, class Allocator = allocator<ranges::range_value_
 
 template <class Allocator> struct hash<std::vector<bool, Allocator>>;
 
-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);
+template <class T, class Allocator> bool operator==(const vector<T,Allocator>& x, const vector<T,Allocator>& y);   // constexpr since C++20
+template <class T, class Allocator> bool operator!=(const vector<T,Allocator>& x, const vector<T,Allocator>& y);   // removed in C++20
+template <class T, class Allocator> bool operator< (const vector<T,Allocator>& x, const vector<T,Allocator>& y);   // removed in C++20
+template <class T, class Allocator> bool operator> (const vector<T,Allocator>& x, const vector<T,Allocator>& y);   // removed in C++20
+template <class T, class Allocator> bool operator>=(const vector<T,Allocator>& x, const vector<T,Allocator>& y);   // removed in C++20
+template <class T, class Allocator> bool operator<=(const vector<T,Allocator>& x, const vector<T,Allocator>& y);   // removed in C++20
+template <class T, class Allocator> constexpr
+  constexpr synth-three-way-result<T> operator<=>(const vector<T, Allocator>& x,
+                                                  const vector<T, Allocator>& y);                                  // since C++20
 
 template <class T, class Allocator>
 void swap(vector<T,Allocator>& x, vector<T,Allocator>& y)
@@ -282,10 +285,10 @@ void swap(vector<T,Allocator>& x, vector<T,Allocator>& y)
 
 template <class T, class Allocator, class U>
 typename vector<T, Allocator>::size_type
-erase(vector<T, Allocator>& c, const U& value);       // C++20
+erase(vector<T, Allocator>& c, const U& value);       // since C++20
 template <class T, class Allocator, class Predicate>
 typename vector<T, Allocator>::size_type
-erase_if(vector<T, Allocator>& c, Predicate pred);    // C++20
+erase_if(vector<T, Allocator>& c, Predicate pred);    // since C++20
 
 
 template<class T>
@@ -303,6 +306,7 @@ template<class T, class charT> requires is-vector-bool-reference<T> // Since C++
 #include <__algorithm/fill_n.h>
 #include <__algorithm/iterator_operations.h>
 #include <__algorithm/lexicographical_compare.h>
+#include <__algorithm/lexicographical_compare_three_way.h>
 #include <__algorithm/remove.h>
 #include <__algorithm/remove_if.h>
 #include <__algorithm/rotate.h>
@@ -3441,8 +3445,9 @@ operator==(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __
     return __sz == __y.size() && std::equal(__x.begin(), __x.end(), __y.begin());
 }
 
+#if _LIBCPP_STD_VER <= 17
+
 template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20
 inline _LIBCPP_HIDE_FROM_ABI
 bool
 operator!=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y)
@@ -3451,7 +3456,6 @@ operator!=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __
 }
 
 template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20
 inline _LIBCPP_HIDE_FROM_ABI
 bool
 operator< (const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y)
@@ -3460,7 +3464,6 @@ operator< (const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __
 }
 
 template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20
 inline _LIBCPP_HIDE_FROM_ABI
 bool
 operator> (const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y)
@@ -3469,7 +3472,6 @@ operator> (const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __
 }
 
 template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20
 inline _LIBCPP_HIDE_FROM_ABI
 bool
 operator>=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y)
@@ -3478,7 +3480,6 @@ operator>=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __
 }
 
 template <class _Tp, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20
 inline _LIBCPP_HIDE_FROM_ABI
 bool
 operator<=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y)
@@ -3486,6 +3487,17 @@ operator<=(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __
     return !(__y < __x);
 }
 
+#else // _LIBCPP_STD_VER <= 17
+
+template <class _Tp, class _Allocator>
+_LIBCPP_HIDE_FROM_ABI constexpr __synth_three_way_result<_Tp>
+operator<=>(const vector<_Tp, _Allocator>& __x, const vector<_Tp, _Allocator>& __y) {
+    return std::lexicographical_compare_three_way(
+        __x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way<_Tp, _Tp>);
+}
+
+#endif // _LIBCPP_STD_VER <= 17
+
 template <class _Tp, class _Allocator>
 _LIBCPP_CONSTEXPR_SINCE_CXX20
 inline _LIBCPP_HIDE_FROM_ABI

diff  --git a/libcxx/test/std/containers/sequences/vector.bool/compare.three_way.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/compare.three_way.pass.cpp
new file mode 100644
index 0000000000000..142589eabf45b
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/vector.bool/compare.three_way.pass.cpp
@@ -0,0 +1,96 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// <vector>
+
+// class vector<bool, Allocator>
+
+// template<class T, class Allocator>
+//   constexpr synth-three-way-result<T> operator<=>(const vector<T, Allocator>& x,
+//                                                   const vector<T, Allocator>& y);
+
+#include <cassert>
+#include <vector>
+
+#include "test_comparisons.h"
+
+constexpr bool test_sequence_container_spaceship_vectorbool() {
+  // Empty containers
+  {
+    std::vector<bool> l1;
+    std::vector<bool> l2;
+    assert(testOrder(l1, l2, std::strong_ordering::equivalent));
+  }
+  // Identical contents
+  {
+    std::vector<bool> t1{true, true};
+    std::vector<bool> t2{true, true};
+    assert(testOrder(t1, t2, std::strong_ordering::equivalent));
+
+    std::vector<bool> f1{false, false};
+    std::vector<bool> f2{false, false};
+    assert(testOrder(f1, f2, std::strong_ordering::equivalent));
+  }
+  // Less, due to contained values
+  {
+    std::vector<bool> l1{true, false};
+    std::vector<bool> l2{true, true};
+    assert(testOrder(l1, l2, std::strong_ordering::less));
+  }
+  // Greater, due to contained values
+  {
+    std::vector<bool> l1{true, true};
+    std::vector<bool> l2{true, false};
+    assert(testOrder(l1, l2, std::strong_ordering::greater));
+  }
+  // Shorter list
+  {
+    std::vector<bool> l1{true};
+    std::vector<bool> l2{true, false};
+    assert(testOrder(l1, l2, std::strong_ordering::less));
+
+    std::vector<bool> t1{true};
+    std::vector<bool> t2{true, true};
+    assert(testOrder(t1, t2, std::strong_ordering::less));
+
+    std::vector<bool> f1{false};
+    std::vector<bool> f2{false, false};
+    assert(testOrder(f1, f2, std::strong_ordering::less));
+
+    std::vector<bool> e;
+    assert(testOrder(e, t1, std::strong_ordering::less));
+    assert(testOrder(e, f1, std::strong_ordering::less));
+  }
+  // Longer list
+  {
+    std::vector<bool> l1{true, false};
+    std::vector<bool> l2{true};
+    assert(testOrder(l1, l2, std::strong_ordering::greater));
+
+    std::vector<bool> t1{true, true};
+    std::vector<bool> t2{true};
+    assert(testOrder(t1, t2, std::strong_ordering::greater));
+
+    std::vector<bool> f1{false, false};
+    std::vector<bool> f2{false};
+    assert(testOrder(f1, f2, std::strong_ordering::greater));
+
+    std::vector<bool> e;
+    assert(testOrder(t2, e, std::strong_ordering::greater));
+    assert(testOrder(f2, e, std::strong_ordering::greater));
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  assert(test_sequence_container_spaceship_vectorbool());
+  static_assert(test_sequence_container_spaceship_vectorbool());
+  return 0;
+}

diff  --git a/libcxx/test/std/containers/sequences/vector/compare.three_way.pass.cpp b/libcxx/test/std/containers/sequences/vector/compare.three_way.pass.cpp
new file mode 100644
index 0000000000000..93b11eef52f63
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/vector/compare.three_way.pass.cpp
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// <vector>
+
+// class vector
+
+// template<class T, class Allocator>
+//   constexpr synth-three-way-result<T> operator<=>(const vector<T, Allocator>& x,
+//                                                   const vector<T, Allocator>& y);
+
+#include <cassert>
+#include <vector>
+
+#include "test_container_comparisons.h"
+
+int main(int, char**) {
+  assert(test_sequence_container_spaceship<std::vector>());
+  static_assert(test_sequence_container_spaceship<std::vector>());
+  return 0;
+}


        


More information about the libcxx-commits mailing list