diff options
author | Hristo Hristov <zingam@outlook.com> | 2023-05-06 15:41:41 +0300 |
---|---|---|
committer | Hristo Hristov <zingam@outlook.com> | 2023-05-08 17:03:06 +0300 |
commit | 254986d2df8d8407b46329e452c16748d29ed4cd (patch) | |
tree | f7e8afaf2d277af6046189b0b566865431842279 /libcxx | |
parent | e875de2a3e8e814265c7cb09b908a444df1a498d (diff) | |
download | llvm-254986d2df8d8407b46329e452c16748d29ed4cd.tar.gz |
[libc++][spaceship] Implement `operator<=>` for `array`
Implements part of P1614R2 "The Mothership has Landed"
Reviewed By: Mordante, #libc, philnik
Differential Revision: https://reviews.llvm.org/D132265
Diffstat (limited to 'libcxx')
9 files changed, 273 insertions, 148 deletions
diff --git a/libcxx/docs/Status/Cxx20Issues.csv b/libcxx/docs/Status/Cxx20Issues.csv index c0143931be01..d9f87112a5e6 100644 --- a/libcxx/docs/Status/Cxx20Issues.csv +++ b/libcxx/docs/Status/Cxx20Issues.csv @@ -259,7 +259,7 @@ "`3338 <https://wg21.link/LWG3338>`__","Rename ``default_constructible``\ to ``default_initializable``\ ","Prague","|Complete|","13.0" "`3340 <https://wg21.link/LWG3340>`__","Formatting functions should throw on argument/format string mismatch in |sect|\ [format.functions]","Prague","|Complete|","14.0","|format|" "`3346 <https://wg21.link/LWG3346>`__","``pair``\ and ``tuple``\ copy and move constructor have backwards specification","Prague","","" -"`3347 <https://wg21.link/LWG3347>`__","``std::pair<T, U>``\ now requires ``T``\ and ``U``\ to be less-than-comparable","Prague","","" +"`3347 <https://wg21.link/LWG3347>`__","``std::pair<T, U>``\ now requires ``T``\ and ``U``\ to be less-than-comparable","Prague","|Complete|","17.0" "`3348 <https://wg21.link/LWG3348>`__","``__cpp_lib_unwrap_ref``\ in wrong header","Prague","|Complete|","12.0" "`3349 <https://wg21.link/LWG3349>`__","Missing ``__cpp_lib_constexpr_complex``\ for P0415R1","Prague","|Complete|","16.0" "`3350 <https://wg21.link/LWG3350>`__","Simplify return type of ``lexicographical_compare_three_way``\ ","Prague","|Complete|","17.0","|spaceship|" diff --git a/libcxx/docs/Status/SpaceshipProjects.csv b/libcxx/docs/Status/SpaceshipProjects.csv index 3eecc354b811..6dd14bdd09db 100644 --- a/libcxx/docs/Status/SpaceshipProjects.csv +++ b/libcxx/docs/Status/SpaceshipProjects.csv @@ -35,7 +35,8 @@ Section,Description,Dependencies,Assignee,Complete | `[stacktrace.basic.cmp] <https://wg21.link/stacktrace.basic.cmp>`_,| `basic_stacktrace <https://reviews.llvm.org/D123228>`_,[alg.three.way],Nikolas Klauser,|In Progress| | `[string.cmp] <https://wg21.link/string.cmp>`_,| `basic_string <https://reviews.llvm.org/D131421>`_,None,Mark de Wever,|Complete| | `[string.view.comparison] <https://wg21.link/string.view.comparison>`_,| `basic_string_view <https://reviews.llvm.org/D130295>`_,None,Mark de Wever,|Complete| -| `[array.syn] <https://wg21.link/array.syn>`_ (`general <https://wg21.link/container.opt.reqmts>`_),| `array <https://reviews.llvm.org/D132265>`_,[expos.only.func],Adrian Vogelsgesang,|In Progress| +| `[array.syn] <https://wg21.link/array.syn>`_ (`general <https://wg21.link/container.opt.reqmts>`_),| `array <https://reviews.llvm.org/D132265>`_,[expos.only.func],"| Adrian Vogelsgesang +| Hristo Hristov",|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| diff --git a/libcxx/include/array b/libcxx/include/array index 58e0fb273f01..5a8a1acca475 100644 --- a/libcxx/include/array +++ b/libcxx/include/array @@ -77,15 +77,18 @@ template <class T, class... U> template <class T, size_t N> bool operator==(const array<T,N>& x, const array<T,N>& y); // constexpr in C++20 template <class T, size_t N> - bool operator!=(const array<T,N>& x, const array<T,N>& y); // constexpr in C++20 + bool operator!=(const array<T,N>& x, const array<T,N>& y); // removed in C++20 template <class T, size_t N> - bool operator<(const array<T,N>& x, const array<T,N>& y); // constexpr in C++20 + bool operator<(const array<T,N>& x, const array<T,N>& y); // removed in C++20 template <class T, size_t N> - bool operator>(const array<T,N>& x, const array<T,N>& y); // constexpr in C++20 + bool operator>(const array<T,N>& x, const array<T,N>& y); // removed in C++20 template <class T, size_t N> - bool operator<=(const array<T,N>& x, const array<T,N>& y); // constexpr in C++20 + bool operator<=(const array<T,N>& x, const array<T,N>& y); // removed in C++20 template <class T, size_t N> - bool operator>=(const array<T,N>& x, const array<T,N>& y); // constexpr in C++20 + bool operator>=(const array<T,N>& x, const array<T,N>& y); // removed in C++20 +template<class T, size_t N> + constexpr synth-three-way-result<T> + operator<=>(const array<T, N>& x, const array<T, N>& y); // since C++20 template <class T, size_t N > void swap(array<T,N>& x, array<T,N>& y) noexcept(noexcept(x.swap(y))); // constexpr in C++20 @@ -111,6 +114,7 @@ template <size_t I, class T, size_t N> const T&& get(const array<T, N>&&) noexce #include <__algorithm/equal.h> #include <__algorithm/fill_n.h> #include <__algorithm/lexicographical_compare.h> +#include <__algorithm/lexicographical_compare_three_way.h> #include <__algorithm/swap_ranges.h> #include <__assert> // all public C++ headers provide the assertion handler #include <__config> @@ -401,47 +405,44 @@ operator==(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) return _VSTD::equal(__x.begin(), __x.end(), __y.begin()); } +#if _LIBCPP_STD_VER <= 17 + template <class _Tp, size_t _Size> -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR_SINCE_CXX20 bool -operator!=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) -{ +inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) { return !(__x == __y); } template <class _Tp, size_t _Size> -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR_SINCE_CXX20 bool -operator<(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) -{ - return _VSTD::lexicographical_compare(__x.begin(), __x.end(), - __y.begin(), __y.end()); +inline _LIBCPP_HIDE_FROM_ABI bool operator<(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) { + return _VSTD::lexicographical_compare(__x.begin(), __x.end(), __y.begin(), __y.end()); } template <class _Tp, size_t _Size> -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR_SINCE_CXX20 bool -operator>(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) -{ +inline _LIBCPP_HIDE_FROM_ABI bool operator>(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) { return __y < __x; } template <class _Tp, size_t _Size> -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR_SINCE_CXX20 bool -operator<=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) -{ +inline _LIBCPP_HIDE_FROM_ABI bool operator<=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) { return !(__y < __x); } template <class _Tp, size_t _Size> -inline _LIBCPP_INLINE_VISIBILITY -_LIBCPP_CONSTEXPR_SINCE_CXX20 bool -operator>=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) -{ +inline _LIBCPP_HIDE_FROM_ABI bool operator>=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) { return !(__x < __y); } +#else // _LIBCPP_STD_VER <= 17 + +template <class _Tp, size_t _Size> +_LIBCPP_HIDE_FROM_ABI constexpr __synth_three_way_result<_Tp> +operator<=>(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __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, size_t _Size> inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 __enable_if_t<_Size == 0 || __is_swappable<_Tp>::value, void> diff --git a/libcxx/test/std/containers/sequences/array/compare.fail.cpp b/libcxx/test/std/containers/sequences/array/compare.fail.cpp deleted file mode 100644 index 1fe4c706b62c..000000000000 --- a/libcxx/test/std/containers/sequences/array/compare.fail.cpp +++ /dev/null @@ -1,68 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -// <array> - -// bool operator==(array<T, N> const&, array<T, N> const&); -// bool operator!=(array<T, N> const&, array<T, N> const&); -// bool operator<(array<T, N> const&, array<T, N> const&); -// bool operator<=(array<T, N> const&, array<T, N> const&); -// bool operator>(array<T, N> const&, array<T, N> const&); -// bool operator>=(array<T, N> const&, array<T, N> const&); - - -#include <array> -#include <vector> -#include <cassert> - -#include "test_macros.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(int, char**) -{ - { - typedef NoCompare<0> T; - typedef std::array<T, 3> C; - C c1 = {{}}; - // expected-error@*:* 2 {{invalid operands to binary expression}} - TEST_IGNORE_NODISCARD (c1 == c1); - TEST_IGNORE_NODISCARD (c1 < c1); - } - { - typedef NoCompare<1> T; - typedef std::array<T, 3> C; - C c1 = {{}}; - // expected-error@*:* 2 {{invalid operands to binary expression}} - TEST_IGNORE_NODISCARD (c1 != c1); - TEST_IGNORE_NODISCARD (c1 > c1); - } - { - typedef NoCompare<2> T; - typedef std::array<T, 0> C; - C c1 = {{}}; - // expected-error@*:* 2 {{invalid operands to binary expression}} - TEST_IGNORE_NODISCARD (c1 == c1); - TEST_IGNORE_NODISCARD (c1 < c1); - } - - return 0; -} diff --git a/libcxx/test/std/containers/sequences/array/compare.pass.cpp b/libcxx/test/std/containers/sequences/array/compare.pass.cpp index 972600992980..f79a638c5688 100644 --- a/libcxx/test/std/containers/sequences/array/compare.pass.cpp +++ b/libcxx/test/std/containers/sequences/array/compare.pass.cpp @@ -8,13 +8,18 @@ // <array> -// bool operator==(array<T, N> const&, array<T, N> const&); // constexpr in C++20 -// bool operator!=(array<T, N> const&, array<T, N> const&); // constexpr in C++20 -// bool operator<(array<T, N> const&, array<T, N> const&); // constexpr in C++20 -// bool operator<=(array<T, N> const&, array<T, N> const&); // constexpr in C++20 -// bool operator>(array<T, N> const&, array<T, N> const&); // constexpr in C++20 -// bool operator>=(array<T, N> const&, array<T, N> const&); // constexpr in C++20 - +// template <class T, size_t N> +// bool operator==(const array<T,N>& x, const array<T,N>& y); // constexpr in C++20 +// template <class T, size_t N> +// bool operator!=(const array<T,N>& x, const array<T,N>& y); // removed in C++20 +// template <class T, size_t N> +// bool operator<(const array<T,N>& x, const array<T,N>& y); // removed in C++20 +// template <class T, size_t N> +// bool operator>(const array<T,N>& x, const array<T,N>& y); // removed in C++20 +// template <class T, size_t N> +// bool operator<=(const array<T,N>& x, const array<T,N>& y); // removed in C++20 +// template <class T, size_t N> +// bool operator>=(const array<T,N>& x, const array<T,N>& y); // removed in C++20 #include <array> #include <cassert> @@ -22,49 +27,53 @@ #include "test_macros.h" #include "test_comparisons.h" -TEST_CONSTEXPR_CXX20 bool tests() -{ - { - typedef std::array<int, 3> C; - const C c1 = {1, 2, 3}; - const C c2 = {1, 2, 3}; - const C c3 = {3, 2, 1}; - const C c4 = {1, 2, 1}; - assert(testComparisons(c1, c2, true, false)); - assert(testComparisons(c1, c3, false, true)); - assert(testComparisons(c1, c4, false, false)); - } - { - typedef std::array<int, 0> C; - const C c1 = {}; - const C c2 = {}; - assert(testComparisons(c1, c2, true, false)); - } - { - typedef std::array<LessAndEqComp, 3> C; - const C c1 = {LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(3)}; - const C c2 = {LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(3)}; - const C c3 = {LessAndEqComp(3), LessAndEqComp(2), LessAndEqComp(1)}; - const C c4 = {LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(1)}; - assert(testComparisons(c1, c2, true, false)); - assert(testComparisons(c1, c3, false, true)); - assert(testComparisons(c1, c4, false, false)); - } - { - typedef std::array<LessAndEqComp, 0> C; - const C c1 = {}; - const C c2 = {}; - assert(testComparisons(c1, c2, true, false)); - } +TEST_CONSTEXPR_CXX20 bool tests() { + // Arrays where the elements support all comparison operators + AssertComparisonsReturnBool<std::array<int, 3> >(); + { + typedef std::array<int, 3> C; + const C c1 = {1, 2, 3}; + const C c2 = {1, 2, 3}; + const C c3 = {3, 2, 1}; + const C c4 = {1, 2, 1}; + assert(testComparisons(c1, c2, true, false)); + assert(testComparisons(c1, c3, false, true)); + assert(testComparisons(c1, c4, false, false)); + } + // Empty array + { + typedef std::array<int, 0> C; + const C c1 = {}; + const C c2 = {}; + assert(testComparisons(c1, c2, true, false)); + } + // Arrays where the elements support only less and equality comparisons + AssertComparisonsReturnBool<std::array<LessAndEqComp, 3> >(); + { + typedef std::array<LessAndEqComp, 3> C; + const C c1 = {LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(3)}; + const C c2 = {LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(3)}; + const C c3 = {LessAndEqComp(3), LessAndEqComp(2), LessAndEqComp(1)}; + const C c4 = {LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(1)}; + assert(testComparisons(c1, c2, true, false)); + assert(testComparisons(c1, c3, false, true)); + assert(testComparisons(c1, c4, false, false)); + } + // Empty array where the elements support only less and equality comparisons + { + typedef std::array<LessAndEqComp, 0> C; + const C c1 = {}; + const C c2 = {}; + assert(testComparisons(c1, c2, true, false)); + } - return true; + return true; } -int main(int, char**) -{ - tests(); +int main(int, char**) { + tests(); #if TEST_STD_VER >= 20 - static_assert(tests(), ""); + static_assert(tests()); #endif - return 0; + return 0; } diff --git a/libcxx/test/std/containers/sequences/array/compare.three_way.pass.cpp b/libcxx/test/std/containers/sequences/array/compare.three_way.pass.cpp new file mode 100644 index 000000000000..01be1db73041 --- /dev/null +++ b/libcxx/test/std/containers/sequences/array/compare.three_way.pass.cpp @@ -0,0 +1,87 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// <array> + +// template<class T, size_t N> +// constexpr synth-three-way-result<T> +// operator<=>(const array<T, N>& x, const array<T, N>& y); + +#include <array> +#include <cassert> + +#include "test_comparisons.h" + +// SFINAE + +constexpr std::size_t N{1}; + +// The container should fulfill `std::three_way_comparable` +static_assert(std::three_way_comparable<std::array<int, N>>); + +// Thanks to SFINAE, the following is not a compiler error but returns `false` +struct NonComparable {}; +static_assert(!std::three_way_comparable<std::array<NonComparable, N>>); + +// Implementation detail of `test_sequence_container_array_spaceship` +template <typename Elem, typename Order> +constexpr void test_sequence_container_array_spaceship_with_type() { + // Empty containers + { + std::array<Elem, 0> l1 = {}; + std::array<Elem, 0> l2 = {}; + assert(testOrder(l1, l2, Order::equivalent)); + } + // Identical contents + { + std::array l1{Elem{1}, Elem{1}}; + std::array l2{Elem{1}, Elem{1}}; + assert(testOrder(l1, l2, Order::equivalent)); + } + // Less, due to contained values + { + std::array l1{Elem{1}, Elem{1}}; + std::array l2{Elem{1}, Elem{2}}; + assert(testOrder(l1, l2, Order::less)); + } + // Greater, due to contained values + { + std::array l1{Elem{1}, Elem{3}}; + std::array l2{Elem{1}, Elem{2}}; + assert(testOrder(l1, l2, Order::greater)); + } + // Shorter list - unsupported - containers must be of equal lengths + // Longer list - unsupported - containers must be of equal lengths + // Unordered + if constexpr (std::is_same_v<Elem, PartialOrder>) { + std::array l1{Elem{1}, Elem{std::numeric_limits<int>::min()}}; + std::array l2{Elem{1}, Elem{2}}; + assert(testOrder(l1, l2, Order::unordered)); + } +} + +// Tests the `operator<=>` on sequence containers `array` +constexpr bool test_sequence_container_array_spaceship() { + // Test different comparison categories + test_sequence_container_array_spaceship_with_type<int, std::strong_ordering>(); + test_sequence_container_array_spaceship_with_type<StrongOrder, std::strong_ordering>(); + test_sequence_container_array_spaceship_with_type<WeakOrder, std::weak_ordering>(); + test_sequence_container_array_spaceship_with_type<PartialOrder, std::partial_ordering>(); + + // `LessAndEqComp` does not have `operator<=>`. Ordering is synthesized based on `operator<` + test_sequence_container_array_spaceship_with_type<LessAndEqComp, std::weak_ordering>(); + + return true; +} + +int main(int, char**) { + assert(test_sequence_container_array_spaceship()); + static_assert(test_sequence_container_array_spaceship()); + return 0; +} diff --git a/libcxx/test/std/containers/sequences/array/compare.three_way.verify.cpp b/libcxx/test/std/containers/sequences/array/compare.three_way.verify.cpp new file mode 100644 index 000000000000..b7267ec9b932 --- /dev/null +++ b/libcxx/test/std/containers/sequences/array/compare.three_way.verify.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// <array> + +// template<class T, size_t N> +// constexpr synth-three-way-result<T> +// operator<=>(const array<T, N>& x, const array<T, N>& y); + +// arrays with different sizes should not compare + +#include <array> + +int main(int, char**) { + { + std::array a1{1}; + std::array a2{1, 2}; + + // expected-error@*:* {{invalid operands to binary expression}} + a1 <=> a2; + } + { + std::array a1{1, 2}; + std::array a2{1}; + + // expected-error@*:* {{invalid operands to binary expression}} + a1 <=> a2; + } + + return 0; +} diff --git a/libcxx/test/std/containers/sequences/array/compare.verify.cpp b/libcxx/test/std/containers/sequences/array/compare.verify.cpp new file mode 100644 index 000000000000..4b001601a4fe --- /dev/null +++ b/libcxx/test/std/containers/sequences/array/compare.verify.cpp @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// <array> + +// template <class T, size_t N> +// bool operator==(const array<T,N>& x, const array<T,N>& y); // constexpr in C++20 +// template <class T, size_t N> +// bool operator!=(const array<T,N>& x, const array<T,N>& y); // removed in C++20 +// template <class T, size_t N> +// bool operator<(const array<T,N>& x, const array<T,N>& y); // removed in C++20 +// template <class T, size_t N> +// bool operator>(const array<T,N>& x, const array<T,N>& y); // removed in C++20 +// template <class T, size_t N> +// bool operator<=(const array<T,N>& x, const array<T,N>& y); // removed in C++20 +// template <class T, size_t N> +// bool operator>=(const array<T,N>& x, const array<T,N>& y); // removed in C++20 + +#include <array> + +#include "test_macros.h" + +template <int> +struct NoCompare {}; + +int main(int, char**) { + { + typedef NoCompare<0> T; + typedef std::array<T, 3> C; + C c1 = {{}}; + // expected-error@*:* 2 {{invalid operands to binary expression}} + TEST_IGNORE_NODISCARD(c1 == c1); + TEST_IGNORE_NODISCARD(c1 < c1); + } + { + typedef NoCompare<1> T; + typedef std::array<T, 3> C; + C c1 = {{}}; + // expected-error@*:* 2 {{invalid operands to binary expression}} + TEST_IGNORE_NODISCARD(c1 != c1); + TEST_IGNORE_NODISCARD(c1 > c1); + } + { + typedef NoCompare<2> T; + typedef std::array<T, 0> C; + C c1 = {{}}; + // expected-error@*:* 2 {{invalid operands to binary expression}} + TEST_IGNORE_NODISCARD(c1 == c1); + TEST_IGNORE_NODISCARD(c1 < c1); + } + + return 0; +} diff --git a/libcxx/test/support/test_container_comparisons.h b/libcxx/test/support/test_container_comparisons.h index 561275c8bb79..f9dae9d6455a 100644 --- a/libcxx/test/support/test_container_comparisons.h +++ b/libcxx/test/support/test_container_comparisons.h @@ -62,7 +62,7 @@ constexpr void test_sequence_container_spaceship_with_type() { // Tests the `operator<=>` on sequence containers template <template <typename...> typename Container> constexpr bool test_sequence_container_spaceship() { - // The container should fulfil `std::three_way_comparable` + // The container should fulfill `std::three_way_comparable` static_assert(std::three_way_comparable<Container<int>>); // Test different comparison categories @@ -71,7 +71,7 @@ constexpr bool test_sequence_container_spaceship() { test_sequence_container_spaceship_with_type<Container, WeakOrder, std::weak_ordering>(); test_sequence_container_spaceship_with_type<Container, PartialOrder, std::partial_ordering>(); - // `LessAndEqComp` does not have `operator<=>`. ordering is sythesized based on `operator<` + // `LessAndEqComp` does not have `operator<=>`. Ordering is synthesized based on `operator<` test_sequence_container_spaceship_with_type<Container, LessAndEqComp, std::weak_ordering>(); // Thanks to SFINAE, the following is not a compiler error but returns `false` @@ -186,7 +186,7 @@ constexpr void test_ordered_map_container_spaceship_with_type() { // Tests the `operator<=>` on ordered containers template <template <typename...> typename Container> constexpr bool test_ordered_map_container_spaceship() { - // The container should fulfil `std::three_way_comparable` + // The container should fulfill `std::three_way_comparable` static_assert(std::three_way_comparable<Container<int, int>>); // Test different comparison categories @@ -195,7 +195,7 @@ constexpr bool test_ordered_map_container_spaceship() { test_ordered_map_container_spaceship_with_type<Container, int, WeakOrder, std::weak_ordering>(); test_ordered_map_container_spaceship_with_type<Container, int, PartialOrder, std::partial_ordering>(); - // `LessAndEqComp` does not have `operator<=>`. ordering is sythesized based on `operator<` + // `LessAndEqComp` does not have `operator<=>`. Ordering is synthesized based on `operator<` test_ordered_map_container_spaceship_with_type<Container, int, LessAndEqComp, std::weak_ordering>(); // Thanks to SFINAE, the following is not a compiler error but returns `false` |