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 @@ -104,6 +104,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))); @@ -394,6 +398,14 @@ _LIBCPP_INLINE_VISIBILITY bool operator< (const queue<_T1, _C1>& __x,const queue<_T1, _C1>& __y); + +#if _LIBCPP_STD_VER >= 20 + + template + friend _LIBCPP_HIDE_FROM_ABI compare_three_way_result_t<_C1> + operator<=>(const queue<_T1, _C1>& __x, const queue<_T1, _C1>& __y); + +#endif }; #if _LIBCPP_STD_VER >= 17 @@ -474,6 +486,16 @@ 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) { + return __x.c <=> __y.c; +} + +#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,29 @@ +//===----------------------------------------------------------------------===// +// +// 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 "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/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 @@ -10,10 +10,106 @@ #ifndef TEST_CONTAINER_COMPARISONS #define TEST_CONTAINER_COMPARISONS +#include +#include #include #include "test_comparisons.h" +//////////////////////////////////////////////////////////////////////////////// +// Custom containers +//////////////////////////////////////////////////////////////////////////////// + +template +class custom_container_iterator : public std::list::iterator {}; + +template +class custom_container { +public: + using value_type = T; + using reference = T&; + using const_reference = const T&; + using iterator = custom_container_iterator; + using const_iterator = const custom_container_iterator; + using difference_type = std::ptrdiff_t; + using size_type = std::size_t; + +public: + custom_container() = default; + custom_container(const custom_container&) = default; + custom_container& operator=(const custom_container&) = default; + custom_container(custom_container&&) = default; + custom_container& operator=(custom_container&&) = default; + ~custom_container() = default; + +public: + custom_container(std::initializer_list values) : data{values} {} + +public: + auto being() { return iterator{}; } + auto end() { return iterator{}; } + + auto cbeing() { return const_iterator{}; } + auto cend() { return const_iterator{}; } + +public: + bool operator==(const custom_container& other) const = default; + + auto operator<=>(const custom_container& other) const = default; + +public: + void swap(custom_container& other) noexcept { swap(this, other); } + + auto size() const { return data.size(); } + + auto max_size() const { return data.max_size(); } + + auto empty() { return data.empty(); } + + template + friend void swap(custom_container&, custom_container&); + +protected: + std::list data; +}; + +template +void swap(custom_container lhs, custom_container rhs) { + std::swap(lhs, rhs); +} + +template +class custom_sequence_container : public custom_container { +public: + custom_sequence_container() = default; + custom_sequence_container(const custom_sequence_container&) = default; + custom_sequence_container& operator=(const custom_sequence_container&) = default; + custom_sequence_container(custom_sequence_container&&) = default; + custom_sequence_container& operator=(custom_sequence_container&&) = default; + ~custom_sequence_container() = default; + +public: + custom_sequence_container(std::initializer_list values) : custom_sequence_container::custom_container{values} {} + +public: + template + auto emplace(typename custom_container::const_iterator pos, Args&&... args) { + return this->data.emplace(pos, std::forward(args)...); + } + + auto insert(T value) { return this->data.insert(value); } + +public: + auto back() { return this->data.back(); }; + auto front() { return this->data.back(); } + void push_back(T data) { this->data.push_back(data); } + void pop_back() { this->data.pop_front(); }; +}; + +//////////////////////////////////////////////////////////////////////////////// +// Test helpers +//////////////////////////////////////////////////////////////////////////////// + // Implementation detail of `test_sequence_container_spaceship` template