diff --git a/libcxx/docs/Status/SpaceshipProjects.csv b/libcxx/docs/Status/SpaceshipProjects.csv --- a/libcxx/docs/Status/SpaceshipProjects.csv +++ b/libcxx/docs/Status/SpaceshipProjects.csv @@ -45,7 +45,7 @@ | `multimap `_",[expos.only.func],Hristo Hristov,|Complete| | `[associative.set.syn] `_ (`general `_),"| multiset | set",[expos.only.func],Hristo Hristov,|In Progress| -| `[queue.ops] `_,| `queue `_,None,Hristo Hristov,|In Progress| +| `[queue.ops] `_,| `queue `_,None,Hristo Hristov,|Complete| | `[stack.ops] `_,| `stack `_,None,Hristo Hristov,|In Progress| | `[reverse.iter.cmp] `_,| `reverse_iterator `_,None,Mikhail Maltsev,|Complete| | `[move.iter.op.comp] `_,| `move_iterator `_,None,Arthur O'Dwyer,|Complete| diff --git a/libcxx/include/queue b/libcxx/include/queue --- a/libcxx/include/queue +++ b/libcxx/include/queue @@ -116,6 +116,10 @@ template bool operator<=(const queue& x,const queue& y); +template + compare_three_way_result_t + operator<=>(const queue& x, const queue& y); // since C++20 + template void swap(queue& x, queue& y) noexcept(noexcept(x.swap(y))); @@ -550,6 +554,17 @@ return !(__y < __x); } +#if _LIBCPP_STD_VER >= 20 + +template +_LIBCPP_HIDE_FROM_ABI compare_three_way_result_t<_Container> +operator<=>(const queue<_Tp, _Container>& __x, const queue<_Tp, _Container>& __y) { + // clang 16 bug: declaring `friend operator<=>` causes "use of overloaded operator '*' is ambiguous" errors + return __x.__get_container() <=> __y.__get_container(); +} + +#endif + template inline _LIBCPP_INLINE_VISIBILITY __enable_if_t<__is_swappable<_Container>::value, void> diff --git a/libcxx/test/std/containers/container.adaptors/queue/queue.ops/compare.three_way.pass.cpp b/libcxx/test/std/containers/container.adaptors/queue/queue.ops/compare.three_way.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/container.adaptors/queue/queue.ops/compare.three_way.pass.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// + +// template +// compare_three_way_result_t +// operator<=>(const queue& x, const queue& y); + +#include +#include +#include +#include + +#include "nasty_containers.h" +#include "test_container_comparisons.h" + +int main(int, char**) { + assert((test_sequence_container_adaptor_spaceship())); + assert((test_sequence_container_adaptor_spaceship())); + assert((test_sequence_container_adaptor_spaceship())); + // `std::queue` is not constexpr, so no `static_assert` test here. + return 0; +} diff --git a/libcxx/test/support/nasty_containers.h b/libcxx/test/support/nasty_containers.h --- a/libcxx/test/support/nasty_containers.h +++ b/libcxx/test/support/nasty_containers.h @@ -138,6 +138,14 @@ template bool operator==(const nasty_vector& x, const nasty_vector& y) { return x.v_ == y.v_; } + +#if TEST_STD_VER >= 20 + +template +auto operator<=>(const nasty_vector& x, const nasty_vector& y) { return x.v_ <=> y.v_; } + +#endif + template class nasty_list { @@ -285,6 +293,13 @@ template bool operator==(const nasty_list& x, const nasty_list& y) { return x.l_ == y.l_; } +#if TEST_STD_VER >= 20 + +template +auto operator<=>(const nasty_list& x, const nasty_list& y) { return x.l_ <=> y.l_; } + +#endif + // Not really a mutex, but can play one in tests class nasty_mutex { diff --git a/libcxx/test/support/test_container_comparisons.h b/libcxx/test/support/test_container_comparisons.h --- a/libcxx/test/support/test_container_comparisons.h +++ b/libcxx/test/support/test_container_comparisons.h @@ -84,6 +84,96 @@ return true; } +// Implementation detail of `test_sequence_container_adaptor_spaceship` +template