"`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|"
| `[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|
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
#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>
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>
+++ /dev/null
-//===----------------------------------------------------------------------===//
-//
-// 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;
-}
// <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>
#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;
}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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;
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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;
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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;
+}
// 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
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`
// 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
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`