libstdc++: Mark <queue>, <deque> constexpr. This patch makes partial progress towards P3372 by marking std::{deque, priority_queue, queue} and relevant internal helpers to be constexpr when using C++26.
libstdc++-v3/ChangeLog: * include/bits/deque.tcc: Mark nonmember functions constexpr. * include/bits/stl_algobase.h: Mark some __equal_aux1 overloads constexpr for deque nonmember functions. * include/bits/stl_deque.h: Make deque and member functions constexpr. * include/bits/stl_queue.h: Make queue, priority_queue, and respective member functions constexpr. * include/bits/stl_uninitialized.h: Mark __uninitialized_default_a constexpr for deque nonmember functions. * include/bits/version.def: Add feature test macros for __cpp_lib_constexpr_{queue, deque}. * include/bits/version.h : Regenerate. * include/std/deque: Mark nonmember functions constexpr and add macros. * include/std/queue: Mark nonmember functions constexpr and add macros. * testsuite/23_containers/deque/constexpr.cc: New test. Tries to exhaust all possible features in standard. * testsuite/23_containers/queue/constexpr.cc: New test. Ditto. * testsuite/23_containers/priority_queue/constexpr.cc: New test. Ditto. Signed-off-by: Thor Preimesberger <tcpreimesber...@gmail.com> --- libstdc++-v3/include/bits/deque.tcc | 34 +++ libstdc++-v3/include/bits/stl_algobase.h | 3 + libstdc++-v3/include/bits/stl_deque.h | 166 ++++++++++- libstdc++-v3/include/bits/stl_queue.h | 73 ++++- libstdc++-v3/include/bits/stl_uninitialized.h | 1 + libstdc++-v3/include/bits/version.def | 16 ++ libstdc++-v3/include/bits/version.h | 20 ++ libstdc++-v3/include/std/deque | 3 + libstdc++-v3/include/std/queue | 1 + .../23_containers/deque/constexpr.cc | 266 ++++++++++++++++++ .../23_containers/priority_queue/constexpr.cc | 233 +++++++++++++++ .../23_containers/queue/constexpr.cc | 194 +++++++++++++ 12 files changed, 1007 insertions(+), 3 deletions(-) create mode 100644 libstdc++-v3/testsuite/23_containers/deque/constexpr.cc create mode 100644 libstdc++-v3/testsuite/23_containers/priority_queue/constexpr.cc create mode 100644 libstdc++-v3/testsuite/23_containers/queue/constexpr.cc diff --git a/libstdc++-v3/include/bits/deque.tcc b/libstdc++-v3/include/bits/deque.tcc index dabb6ec5365..ae05bf3b4bc 100644 --- a/libstdc++-v3/include/bits/deque.tcc +++ b/libstdc++-v3/include/bits/deque.tcc @@ -65,6 +65,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #if __cplusplus >= 201103L template <typename _Tp, typename _Alloc> + _GLIBCXX26_CONSTEXPR void deque<_Tp, _Alloc>:: _M_default_initialize() @@ -91,6 +92,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #endif template <typename _Tp, typename _Alloc> + _GLIBCXX26_CONSTEXPR deque<_Tp, _Alloc>& deque<_Tp, _Alloc>:: operator=(const deque& __x) @@ -133,6 +135,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Tp, typename _Alloc> template<typename... _Args> #if __cplusplus > 201402L + _GLIBCXX26_CONSTEXPR typename deque<_Tp, _Alloc>::reference #else void @@ -157,6 +160,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Tp, typename _Alloc> template<typename... _Args> #if __cplusplus > 201402L + _GLIBCXX26_CONSTEXPR typename deque<_Tp, _Alloc>::reference #else void @@ -183,6 +187,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #if __cplusplus >= 201103L template<typename _Tp, typename _Alloc> template<typename... _Args> + _GLIBCXX26_CONSTEXPR typename deque<_Tp, _Alloc>::iterator deque<_Tp, _Alloc>:: emplace(const_iterator __position, _Args&&... __args) @@ -206,6 +211,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #endif template <typename _Tp, typename _Alloc> + _GLIBCXX26_CONSTEXPR typename deque<_Tp, _Alloc>::iterator deque<_Tp, _Alloc>:: #if __cplusplus >= 201103L @@ -231,6 +237,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } template <typename _Tp, typename _Alloc> + _GLIBCXX26_CONSTEXPR typename deque<_Tp, _Alloc>::iterator deque<_Tp, _Alloc>:: _M_erase(iterator __position) @@ -254,6 +261,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } template <typename _Tp, typename _Alloc> + _GLIBCXX26_CONSTEXPR typename deque<_Tp, _Alloc>::iterator deque<_Tp, _Alloc>:: _M_erase(iterator __first, iterator __last) @@ -303,6 +311,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } template <typename _Tp, typename _Alloc> + _GLIBCXX26_CONSTEXPR void deque<_Tp, _Alloc>:: _M_fill_insert(iterator __pos, size_type __n, const value_type& __x) @@ -346,6 +355,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #if __cplusplus >= 201103L template <typename _Tp, typename _Alloc> + _GLIBCXX26_CONSTEXPR void deque<_Tp, _Alloc>:: _M_default_append(size_type __n) @@ -370,6 +380,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } template <typename _Tp, typename _Alloc> + _GLIBCXX26_CONSTEXPR bool deque<_Tp, _Alloc>:: _M_shrink_to_fit() @@ -389,6 +400,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #endif template <typename _Tp, typename _Alloc> + _GLIBCXX26_CONSTEXPR void deque<_Tp, _Alloc>:: _M_fill_initialize(const value_type& __value) @@ -415,6 +427,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template <typename _Tp, typename _Alloc> template <typename _InputIterator> + _GLIBCXX26_CONSTEXPR void deque<_Tp, _Alloc>:: _M_range_initialize(_InputIterator __first, _InputIterator __last, @@ -439,6 +452,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template <typename _Tp, typename _Alloc> template <typename _ForwardIterator> + _GLIBCXX26_CONSTEXPR void deque<_Tp, _Alloc>:: _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last, @@ -480,6 +494,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Tp, typename _Alloc> #if __cplusplus >= 201103L template<typename... _Args> + _GLIBCXX26_CONSTEXPR void deque<_Tp, _Alloc>:: _M_push_back_aux(_Args&&... __args) @@ -519,6 +534,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Tp, typename _Alloc> #if __cplusplus >= 201103L template<typename... _Args> + _GLIBCXX26_CONSTEXPR void deque<_Tp, _Alloc>:: _M_push_front_aux(_Args&&... __args) @@ -557,6 +573,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // Called only if _M_impl._M_finish._M_cur == _M_impl._M_finish._M_first. template <typename _Tp, typename _Alloc> + _GLIBCXX26_CONSTEXPR void deque<_Tp, _Alloc>:: _M_pop_back_aux() { @@ -573,6 +590,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // _M_impl._M_start._M_cur == _M_impl._M_start._M_last, // then the deque must have at least two nodes. template <typename _Tp, typename _Alloc> + _GLIBCXX26_CONSTEXPR void deque<_Tp, _Alloc>:: _M_pop_front_aux() { @@ -585,6 +603,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template <typename _Tp, typename _Alloc> template <typename _InputIterator, typename _Sentinel> + _GLIBCXX26_CONSTEXPR void deque<_Tp, _Alloc>:: _M_range_prepend(_InputIterator __first, _Sentinel __last, @@ -607,6 +626,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template <typename _Tp, typename _Alloc> template <typename _InputIterator, typename _Sentinel> + _GLIBCXX26_CONSTEXPR void deque<_Tp, _Alloc>:: _M_range_append(_InputIterator __first, _Sentinel __last, @@ -630,6 +650,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template <typename _Tp, typename _Alloc> template <typename _InputIterator> + _GLIBCXX26_CONSTEXPR void deque<_Tp, _Alloc>:: _M_range_insert_aux(iterator __pos, @@ -639,6 +660,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template <typename _Tp, typename _Alloc> template <typename _ForwardIterator> + _GLIBCXX26_CONSTEXPR void deque<_Tp, _Alloc>:: _M_range_insert_aux(iterator __pos, @@ -660,6 +682,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Tp, typename _Alloc> #if __cplusplus >= 201103L template<typename... _Args> + _GLIBCXX26_CONSTEXPR typename deque<_Tp, _Alloc>::iterator deque<_Tp, _Alloc>:: _M_emplace_aux(iterator __pos, _Args&&... __args) @@ -907,6 +930,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Tp, typename _Alloc> template<__detail::__container_compatible_range<_Tp> _Rg> + _GLIBCXX26_CONSTEXPR auto deque<_Tp, _Alloc>:: insert_range(const_iterator __pos, _Rg&& __rg) @@ -947,6 +971,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Tp, typename _Alloc> template<__detail::__container_compatible_range<_Tp> _Rg> + _GLIBCXX26_CONSTEXPR void deque<_Tp, _Alloc>:: prepend_range(_Rg&& __rg) @@ -989,6 +1014,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Tp, typename _Alloc> template<__detail::__container_compatible_range<_Tp> _Rg> + _GLIBCXX26_CONSTEXPR void deque<_Tp, _Alloc>:: append_range(_Rg&& __rg) @@ -1025,6 +1051,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #endif // containers_ranges template<typename _Tp, typename _Alloc> + _GLIBCXX26_CONSTEXPR void deque<_Tp, _Alloc>:: _M_destroy_data_aux(iterator __first, iterator __last) @@ -1047,6 +1074,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } template <typename _Tp, typename _Alloc> + _GLIBCXX26_CONSTEXPR void deque<_Tp, _Alloc>:: _M_new_elements_at_front(size_type __new_elems) @@ -1072,6 +1100,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } template <typename _Tp, typename _Alloc> + _GLIBCXX26_CONSTEXPR void deque<_Tp, _Alloc>:: _M_new_elements_at_back(size_type __new_elems) @@ -1097,6 +1126,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } template <typename _Tp, typename _Alloc> + _GLIBCXX26_CONSTEXPR void deque<_Tp, _Alloc>:: _M_reallocate_map(size_type __nodes_to_add, bool __add_at_front) @@ -1371,6 +1401,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER } template<typename _Tp, typename _Ref, typename _Ptr, typename _II> + _GLIBCXX26_CONSTEXPR bool __equal_dit( const _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>& __first1, @@ -1398,6 +1429,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER } template<typename _Tp, typename _Ref, typename _Ptr, typename _II> + _GLIBCXX26_CONSTEXPR typename __gnu_cxx::__enable_if< __is_random_access_iter<_II>::__value, bool>::__type __equal_aux1(_GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __first1, @@ -1407,6 +1439,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER template<typename _Tp1, typename _Ref1, typename _Ptr1, typename _Tp2, typename _Ref2, typename _Ptr2> + _GLIBCXX26_CONSTEXPR bool __equal_aux1(_GLIBCXX_STD_C::_Deque_iterator<_Tp1, _Ref1, _Ptr1> __first1, _GLIBCXX_STD_C::_Deque_iterator<_Tp1, _Ref1, _Ptr1> __last1, @@ -1414,6 +1447,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER { return std::__equal_dit(__first1, __last1, __first2); } template<typename _II, typename _Tp, typename _Ref, typename _Ptr> + _GLIBCXX26_CONSTEXPR typename __gnu_cxx::__enable_if< __is_random_access_iter<_II>::__value, bool>::__type __equal_aux1(_II __first1, _II __last1, diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h index b104ec2536a..6d82be2c5c3 100644 --- a/libstdc++-v3/include/bits/stl_algobase.h +++ b/libstdc++-v3/include/bits/stl_algobase.h @@ -1216,6 +1216,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER }; template<typename _Tp, typename _Ref, typename _Ptr, typename _II> + _GLIBCXX26_CONSTEXPR typename __gnu_cxx::__enable_if< __is_random_access_iter<_II>::__value, bool>::__type __equal_aux1(_GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>, @@ -1224,12 +1225,14 @@ _GLIBCXX_END_NAMESPACE_CONTAINER template<typename _Tp1, typename _Ref1, typename _Ptr1, typename _Tp2, typename _Ref2, typename _Ptr2> + _GLIBCXX26_CONSTEXPR bool __equal_aux1(_GLIBCXX_STD_C::_Deque_iterator<_Tp1, _Ref1, _Ptr1>, _GLIBCXX_STD_C::_Deque_iterator<_Tp1, _Ref1, _Ptr1>, _GLIBCXX_STD_C::_Deque_iterator<_Tp2, _Ref2, _Ptr2>); template<typename _II, typename _Tp, typename _Ref, typename _Ptr> + _GLIBCXX26_CONSTEXPR typename __gnu_cxx::__enable_if< __is_random_access_iter<_II>::__value, bool>::__type __equal_aux1(_II, _II, diff --git a/libstdc++-v3/include/bits/stl_deque.h b/libstdc++-v3/include/bits/stl_deque.h index 7055641ad4e..e7997a2669b 100644 --- a/libstdc++-v3/include/bits/stl_deque.h +++ b/libstdc++-v3/include/bits/stl_deque.h @@ -131,6 +131,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER typedef __ptr_rebind<_Ptr, _Elt_pointer> _Map_pointer; #endif + _GLIBCXX26_CONSTEXPR static size_t _S_buffer_size() _GLIBCXX_NOEXCEPT { return __deque_buf_size(sizeof(_Tp)); } @@ -147,10 +148,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Elt_pointer _M_last; _Map_pointer _M_node; + _GLIBCXX26_CONSTEXPR _Deque_iterator(_Elt_pointer __x, _Map_pointer __y) _GLIBCXX_NOEXCEPT : _M_cur(__x), _M_first(*__y), _M_last(*__y + _S_buffer_size()), _M_node(__y) { } + _GLIBCXX26_CONSTEXPR _Deque_iterator() _GLIBCXX_NOEXCEPT : _M_cur(), _M_first(), _M_last(), _M_node() { } @@ -164,10 +167,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template<typename _Iter, typename = _Require<is_same<_Self, const_iterator>, is_same<_Iter, iterator>>> + _GLIBCXX26_CONSTEXPR _Deque_iterator(const _Iter& __x) noexcept : _M_cur(__x._M_cur), _M_first(__x._M_first), _M_last(__x._M_last), _M_node(__x._M_node) { } + _GLIBCXX26_CONSTEXPR _Deque_iterator(const _Deque_iterator& __x) noexcept : _M_cur(__x._M_cur), _M_first(__x._M_first), _M_last(__x._M_last), _M_node(__x._M_node) { } @@ -175,20 +180,24 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Deque_iterator& operator=(const _Deque_iterator&) = default; #endif + _GLIBCXX26_CONSTEXPR iterator _M_const_cast() const _GLIBCXX_NOEXCEPT { return iterator(_M_cur, _M_node); } _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR reference operator*() const _GLIBCXX_NOEXCEPT { return *_M_cur; } _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR pointer operator->() const _GLIBCXX_NOEXCEPT { return _M_cur; } + _GLIBCXX26_CONSTEXPR _Self& operator++() _GLIBCXX_NOEXCEPT { @@ -201,6 +210,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER return *this; } + _GLIBCXX26_CONSTEXPR _Self operator++(int) _GLIBCXX_NOEXCEPT { @@ -209,6 +219,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER return __tmp; } + _GLIBCXX26_CONSTEXPR _Self& operator--() _GLIBCXX_NOEXCEPT { @@ -221,6 +232,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER return *this; } + _GLIBCXX26_CONSTEXPR _Self operator--(int) _GLIBCXX_NOEXCEPT { @@ -229,6 +241,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER return __tmp; } + _GLIBCXX26_CONSTEXPR _Self& operator+=(difference_type __n) _GLIBCXX_NOEXCEPT { @@ -248,11 +261,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER return *this; } + _GLIBCXX26_CONSTEXPR _Self& operator-=(difference_type __n) _GLIBCXX_NOEXCEPT { return *this += -__n; } _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR reference operator[](difference_type __n) const _GLIBCXX_NOEXCEPT { return *(*this + __n); } @@ -262,6 +277,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * _M_cur, which should therefore be set by the caller * immediately afterwards, based on _M_first and _M_last. */ + _GLIBCXX26_CONSTEXPR void _M_set_node(_Map_pointer __new_node) _GLIBCXX_NOEXCEPT { @@ -271,6 +287,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR friend bool operator==(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT { return __x._M_cur == __y._M_cur; } @@ -280,6 +297,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // operators are in scope (for additional details, see libstdc++/3628) template<typename _RefR, typename _PtrR> _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR friend bool operator==(const _Self& __x, const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) @@ -288,6 +306,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #if __cpp_lib_three_way_comparison [[nodiscard]] + _GLIBCXX26_CONSTEXPR friend strong_ordering operator<=>(const _Self& __x, const _Self& __y) noexcept { @@ -369,6 +388,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #endif // three-way comparison _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR friend difference_type operator-(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT { @@ -384,6 +404,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // parameters. template<typename _RefR, typename _PtrR> _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR friend difference_type operator-(const _Self& __x, const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) @@ -396,6 +417,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR friend _Self operator+(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT { @@ -405,6 +427,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR friend _Self operator-(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT { @@ -414,6 +437,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR friend _Self operator+(difference_type __n, const _Self& __x) _GLIBCXX_NOEXCEPT { return __x + __n; } @@ -451,6 +475,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER typedef _Alloc allocator_type; + _GLIBCXX26_CONSTEXPR allocator_type get_allocator() const _GLIBCXX_NOEXCEPT { return allocator_type(_M_get_Tp_allocator()); } @@ -458,23 +483,28 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER typedef _Deque_iterator<_Tp, _Tp&, _Ptr> iterator; typedef _Deque_iterator<_Tp, const _Tp&, _Ptr_const> const_iterator; + _GLIBCXX26_CONSTEXPR _Deque_base() : _M_impl() { _M_initialize_map(0); } + _GLIBCXX26_CONSTEXPR _Deque_base(size_t __num_elements) : _M_impl() { _M_initialize_map(__num_elements); } + _GLIBCXX26_CONSTEXPR _Deque_base(const allocator_type& __a, size_t __num_elements) : _M_impl(__a) { _M_initialize_map(__num_elements); } + _GLIBCXX26_CONSTEXPR _Deque_base(const allocator_type& __a) : _M_impl(__a) { /* Caller must initialize map. */ } #if __cplusplus >= 201103L + _GLIBCXX26_CONSTEXPR _Deque_base(_Deque_base&& __x) : _M_impl(std::move(__x._M_get_Tp_allocator())) { @@ -483,10 +513,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER this->_M_impl._M_swap_data(__x._M_impl); } + _GLIBCXX26_CONSTEXPR _Deque_base(_Deque_base&& __x, const allocator_type& __a) : _M_impl(std::move(__x._M_impl), _Tp_alloc_type(__a)) { __x._M_initialize_map(0); } + _GLIBCXX26_CONSTEXPR _Deque_base(_Deque_base&& __x, const allocator_type& __a, size_t __n) : _M_impl(__a) { @@ -505,6 +537,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } #endif + _GLIBCXX26_CONSTEXPR ~_Deque_base() _GLIBCXX_NOEXCEPT; typedef typename iterator::_Map_pointer _Map_pointer; @@ -516,20 +549,25 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER iterator _M_start; iterator _M_finish; + _GLIBCXX26_CONSTEXPR _Deque_impl_data() _GLIBCXX_NOEXCEPT : _M_map(), _M_map_size(), _M_start(), _M_finish() { } #if __cplusplus >= 201103L + _GLIBCXX26_CONSTEXPR _Deque_impl_data(const _Deque_impl_data&) = default; + _GLIBCXX26_CONSTEXPR _Deque_impl_data& operator=(const _Deque_impl_data&) = default; + _GLIBCXX26_CONSTEXPR _Deque_impl_data(_Deque_impl_data&& __x) noexcept : _Deque_impl_data(__x) { __x = _Deque_impl_data(); } #endif + _GLIBCXX26_CONSTEXPR void _M_swap_data(_Deque_impl_data& __x) _GLIBCXX_NOEXCEPT { @@ -545,40 +583,49 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER struct _Deque_impl : public _Tp_alloc_type, public _Deque_impl_data { + _GLIBCXX26_CONSTEXPR _Deque_impl() _GLIBCXX_NOEXCEPT_IF( is_nothrow_default_constructible<_Tp_alloc_type>::value) : _Tp_alloc_type() { } + _GLIBCXX26_CONSTEXPR _Deque_impl(const _Tp_alloc_type& __a) _GLIBCXX_NOEXCEPT : _Tp_alloc_type(__a) { } #if __cplusplus >= 201103L + _GLIBCXX26_CONSTEXPR _Deque_impl(_Deque_impl&&) = default; + _GLIBCXX26_CONSTEXPR _Deque_impl(_Tp_alloc_type&& __a) noexcept : _Tp_alloc_type(std::move(__a)) { } + _GLIBCXX26_CONSTEXPR _Deque_impl(_Deque_impl&& __d, _Tp_alloc_type&& __a) : _Tp_alloc_type(std::move(__a)), _Deque_impl_data(std::move(__d)) { } #endif }; + _GLIBCXX26_CONSTEXPR _Tp_alloc_type& _M_get_Tp_allocator() _GLIBCXX_NOEXCEPT { return this->_M_impl; } + _GLIBCXX26_CONSTEXPR const _Tp_alloc_type& _M_get_Tp_allocator() const _GLIBCXX_NOEXCEPT { return this->_M_impl; } + _GLIBCXX26_CONSTEXPR _Map_alloc_type _M_get_map_allocator() const _GLIBCXX_NOEXCEPT { return _Map_alloc_type(_M_get_Tp_allocator()); } + _GLIBCXX26_CONSTEXPR _Ptr _M_allocate_node() { @@ -586,6 +633,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER return _Traits::allocate(_M_impl, __deque_buf_size(sizeof(_Tp))); } + _GLIBCXX26_CONSTEXPR void _M_deallocate_node(_Ptr __p) _GLIBCXX_NOEXCEPT { @@ -593,6 +641,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Traits::deallocate(_M_impl, __p, __deque_buf_size(sizeof(_Tp))); } + _GLIBCXX26_CONSTEXPR _Map_pointer _M_allocate_map(size_t __n) { @@ -600,6 +649,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER return _Map_alloc_traits::allocate(__map_alloc, __n); } + _GLIBCXX26_CONSTEXPR void _M_deallocate_map(_Map_pointer __p, size_t __n) _GLIBCXX_NOEXCEPT { @@ -607,8 +657,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Map_alloc_traits::deallocate(__map_alloc, __p, __n); } + _GLIBCXX26_CONSTEXPR void _M_initialize_map(size_t); + _GLIBCXX26_CONSTEXPR void _M_create_nodes(_Map_pointer __nstart, _Map_pointer __nfinish); + _GLIBCXX26_CONSTEXPR void _M_destroy_nodes(_Map_pointer __nstart, _Map_pointer __nfinish) _GLIBCXX_NOEXCEPT; enum { _S_initial_map_size = 8 }; @@ -617,6 +670,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER }; template<typename _Tp, typename _Alloc> + _GLIBCXX26_CONSTEXPR _Deque_base<_Tp, _Alloc>:: ~_Deque_base() _GLIBCXX_NOEXCEPT { @@ -637,6 +691,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * The initial underlying memory layout is a bit complicated... */ template<typename _Tp, typename _Alloc> + _GLIBCXX26_CONSTEXPR void _Deque_base<_Tp, _Alloc>:: _M_initialize_map(size_t __num_elements) @@ -676,6 +731,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } template<typename _Tp, typename _Alloc> + _GLIBCXX26_CONSTEXPR void _Deque_base<_Tp, _Alloc>:: _M_create_nodes(_Map_pointer __nstart, _Map_pointer __nfinish) @@ -694,6 +750,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } template<typename _Tp, typename _Alloc> + _GLIBCXX26_CONSTEXPR void _Deque_base<_Tp, _Alloc>:: _M_destroy_nodes(_Map_pointer __nstart, @@ -828,6 +885,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER typedef _Alloc allocator_type; private: + _GLIBCXX26_CONSTEXPR static size_t _S_buffer_size() _GLIBCXX_NOEXCEPT { return __deque_buf_size(sizeof(_Tp)); } @@ -854,6 +912,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER /** * @brief Creates a %deque with no elements. */ + _GLIBCXX26_CONSTEXPR #if __cplusplus >= 201103L deque() = default; #else @@ -864,6 +923,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @brief Creates a %deque with no elements. * @param __a An allocator object. */ + _GLIBCXX26_CONSTEXPR explicit deque(const allocator_type& __a) : _Base(__a, 0) { } @@ -877,6 +937,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * This constructor fills the %deque with @a n default * constructed elements. */ + _GLIBCXX26_CONSTEXPR explicit deque(size_type __n, const allocator_type& __a = allocator_type()) : _Base(__a, _S_check_init_len(__n, __a)) @@ -890,6 +951,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * * This constructor fills the %deque with @a __n copies of @a __value. */ + _GLIBCXX26_CONSTEXPR deque(size_type __n, const value_type& __value, const allocator_type& __a = allocator_type()) : _Base(__a, _S_check_init_len(__n, __a)) @@ -917,6 +979,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * The newly-created %deque uses a copy of the allocator object used * by @a __x (unless the allocator traits dictate a different object). */ + _GLIBCXX26_CONSTEXPR deque(const deque& __x) : _Base(_Alloc_traits::_S_select_on_copy(__x._M_get_Tp_allocator()), __x.size()) @@ -933,9 +996,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * The contents of the moved instance are a valid, but unspecified * %deque. */ + _GLIBCXX26_CONSTEXPR deque(deque&&) = default; /// Copy constructor with alternative allocator + _GLIBCXX26_CONSTEXPR deque(const deque& __x, const __type_identity_t<allocator_type>& __a) : _Base(__a, __x.size()) { std::__uninitialized_copy_a(__x.begin(), __x.end(), @@ -943,15 +1008,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_get_Tp_allocator()); } /// Move constructor with alternative allocator + _GLIBCXX26_CONSTEXPR deque(deque&& __x, const __type_identity_t<allocator_type>& __a) : deque(std::move(__x), __a, typename _Alloc_traits::is_always_equal{}) { } private: + _GLIBCXX26_CONSTEXPR deque(deque&& __x, const allocator_type& __a, true_type) : _Base(std::move(__x), __a) { } + _GLIBCXX26_CONSTEXPR deque(deque&& __x, const allocator_type& __a, false_type) : _Base(std::move(__x), __a, __x.size()) { @@ -976,6 +1044,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * This will call the element type's copy constructor N times * (where N is __l.size()) and do no memory reallocation. */ + _GLIBCXX26_CONSTEXPR deque(initializer_list<value_type> __l, const allocator_type& __a = allocator_type()) : _Base(__a) @@ -1003,6 +1072,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #if __cplusplus >= 201103L template<typename _InputIterator, typename = std::_RequireInputIter<_InputIterator>> + _GLIBCXX26_CONSTEXPR deque(_InputIterator __first, _InputIterator __last, const allocator_type& __a = allocator_type()) : _Base(__a) @@ -1029,6 +1099,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @since C++23 */ template<__detail::__container_compatible_range<_Tp> _Rg> + _GLIBCXX26_CONSTEXPR deque(from_range_t, _Rg&& __rg, const allocator_type& __a = _Alloc()) : deque(__a) { append_range(std::forward<_Rg>(__rg)); } @@ -1039,6 +1110,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * themselves are pointers, the pointed-to memory is not touched in any * way. Managing the pointer is the user's responsibility. */ + _GLIBCXX26_CONSTEXPR ~deque() { _M_destroy_data(begin(), end(), _M_get_Tp_allocator()); } @@ -1051,6 +1123,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * The newly-created %deque uses a copy of the allocator object used * by @a __x (unless the allocator traits dictate a different object). */ + _GLIBCXX26_CONSTEXPR deque& operator=(const deque& __x); @@ -1063,6 +1136,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * if the allocators permit it). * @a __x is a valid, but unspecified %deque. */ + _GLIBCXX26_CONSTEXPR deque& operator=(deque&& __x) noexcept(_Alloc_traits::_S_always_equal()) { @@ -1082,6 +1156,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * resulting %deque's size is the same as the number of elements * assigned. */ + _GLIBCXX26_CONSTEXPR deque& operator=(initializer_list<value_type> __l) { @@ -1101,6 +1176,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * %deque and that the resulting %deque's size is the same as * the number of elements assigned. */ + _GLIBCXX26_CONSTEXPR void assign(size_type __n, const value_type& __val) { _M_fill_assign(__n, __val); } @@ -1120,6 +1196,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #if __cplusplus >= 201103L template<typename _InputIterator, typename = std::_RequireInputIter<_InputIterator>> + _GLIBCXX26_CONSTEXPR void assign(_InputIterator __first, _InputIterator __last) { _M_assign_aux(__first, __last, std::__iterator_category(__first)); } @@ -1145,6 +1222,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * resulting %deque's size is the same as the number of elements * assigned. */ + _GLIBCXX26_CONSTEXPR void assign(initializer_list<value_type> __l) { _M_assign_aux(__l.begin(), __l.end(), random_access_iterator_tag()); } @@ -1199,6 +1277,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER /// Get a copy of the memory allocation object. _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR allocator_type get_allocator() const _GLIBCXX_NOEXCEPT { return _Base::get_allocator(); } @@ -1209,6 +1288,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * %deque. Iteration is done in ordinary element order. */ _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR iterator begin() _GLIBCXX_NOEXCEPT { return this->_M_impl._M_start; } @@ -1218,6 +1298,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * element in the %deque. Iteration is done in ordinary element order. */ _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR const_iterator begin() const _GLIBCXX_NOEXCEPT { return this->_M_impl._M_start; } @@ -1228,6 +1309,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * element order. */ _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR iterator end() _GLIBCXX_NOEXCEPT { return this->_M_impl._M_finish; } @@ -1238,6 +1320,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * ordinary element order. */ _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR const_iterator end() const _GLIBCXX_NOEXCEPT { return this->_M_impl._M_finish; } @@ -1248,6 +1331,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * element order. */ _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR reverse_iterator rbegin() _GLIBCXX_NOEXCEPT { return reverse_iterator(this->_M_impl._M_finish); } @@ -1258,6 +1342,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * reverse element order. */ _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR const_reverse_iterator rbegin() const _GLIBCXX_NOEXCEPT { return const_reverse_iterator(this->_M_impl._M_finish); } @@ -1268,6 +1353,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * in reverse element order. */ _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR reverse_iterator rend() _GLIBCXX_NOEXCEPT { return reverse_iterator(this->_M_impl._M_start); } @@ -1278,6 +1364,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * done in reverse element order. */ _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR const_reverse_iterator rend() const _GLIBCXX_NOEXCEPT { return const_reverse_iterator(this->_M_impl._M_start); } @@ -1288,6 +1375,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * element in the %deque. Iteration is done in ordinary element order. */ [[__nodiscard__]] + _GLIBCXX26_CONSTEXPR const_iterator cbegin() const noexcept { return this->_M_impl._M_start; } @@ -1298,6 +1386,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * ordinary element order. */ [[__nodiscard__]] + _GLIBCXX26_CONSTEXPR const_iterator cend() const noexcept { return this->_M_impl._M_finish; } @@ -1308,6 +1397,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * reverse element order. */ [[__nodiscard__]] + _GLIBCXX26_CONSTEXPR const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(this->_M_impl._M_finish); } @@ -1318,6 +1408,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * done in reverse element order. */ [[__nodiscard__]] + _GLIBCXX26_CONSTEXPR const_reverse_iterator crend() const noexcept { return const_reverse_iterator(this->_M_impl._M_start); } @@ -1326,6 +1417,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // [23.2.1.2] capacity /** Returns the number of elements in the %deque. */ _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR size_type size() const _GLIBCXX_NOEXCEPT { @@ -1337,6 +1429,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER /** Returns the size() of the largest possible %deque. */ _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR size_type max_size() const _GLIBCXX_NOEXCEPT { return _S_max_size(_M_get_Tp_allocator()); } @@ -1351,6 +1444,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * %deque's current size the %deque is truncated, otherwise * default constructed elements are appended. */ + _GLIBCXX26_CONSTEXPR void resize(size_type __new_size) { @@ -1373,6 +1467,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * %deque is extended and new elements are populated with given * data. */ + _GLIBCXX26_CONSTEXPR void resize(size_type __new_size, const value_type& __x) #else @@ -1401,6 +1496,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #if __cplusplus >= 201103L /** A non-binding request to reduce memory use. */ + _GLIBCXX26_CONSTEXPR void shrink_to_fit() noexcept { _M_shrink_to_fit(); } @@ -1410,7 +1506,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * Returns true if the %deque is empty. (Thus begin() would * equal end().) */ - _GLIBCXX_NODISCARD bool + _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR + bool empty() const _GLIBCXX_NOEXCEPT { return this->_M_impl._M_finish == this->_M_impl._M_start; } @@ -1427,6 +1525,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * see at().) */ _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR reference operator[](size_type __n) _GLIBCXX_NOEXCEPT { @@ -1446,6 +1545,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * see at().) */ _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR const_reference operator[](size_type __n) const _GLIBCXX_NOEXCEPT { @@ -1477,6 +1577,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * is first checked that it is in the range of the deque. The * function throws out_of_range if the check fails. */ + _GLIBCXX26_CONSTEXPR reference at(size_type __n) { @@ -1495,6 +1596,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * checked that it is in the range of the deque. The function throws * out_of_range if the check fails. */ + _GLIBCXX26_CONSTEXPR const_reference at(size_type __n) const { @@ -1507,6 +1609,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * element of the %deque. */ _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR reference front() _GLIBCXX_NOEXCEPT { @@ -1519,6 +1622,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * element of the %deque. */ _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR const_reference front() const _GLIBCXX_NOEXCEPT { @@ -1531,6 +1635,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * %deque. */ _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR reference back() _GLIBCXX_NOEXCEPT { @@ -1545,6 +1650,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * element of the %deque. */ _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR const_reference back() const _GLIBCXX_NOEXCEPT { @@ -1564,6 +1670,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * data to it. Due to the nature of a %deque this operation * can be done in constant time. */ + _GLIBCXX26_CONSTEXPR void push_front(const value_type& __x) { @@ -1579,12 +1686,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } #if __cplusplus >= 201103L + _GLIBCXX26_CONSTEXPR void push_front(value_type&& __x) { emplace_front(std::move(__x)); } template<typename... _Args> #if __cplusplus > 201402L + _GLIBCXX26_CONSTEXPR reference #else void @@ -1601,6 +1710,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * to it. Due to the nature of a %deque this operation can be * done in constant time. */ + _GLIBCXX26_CONSTEXPR void push_back(const value_type& __x) { @@ -1616,12 +1726,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } #if __cplusplus >= 201103L + _GLIBCXX26_CONSTEXPR void push_back(value_type&& __x) { emplace_back(std::move(__x)); } template<typename... _Args> #if __cplusplus > 201402L + _GLIBCXX26_CONSTEXPR reference #else void @@ -1637,6 +1749,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * Note that no data is returned, and if the first element's data is * needed, it should be retrieved before pop_front() is called. */ + _GLIBCXX26_CONSTEXPR void pop_front() _GLIBCXX_NOEXCEPT { @@ -1660,6 +1773,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * Note that no data is returned, and if the last element's data is * needed, it should be retrieved before pop_back() is called. */ + _GLIBCXX26_CONSTEXPR void pop_back() _GLIBCXX_NOEXCEPT { @@ -1686,6 +1800,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * with T(std::forward<Args>(args)...) before the specified location. */ template<typename... _Args> + _GLIBCXX26_CONSTEXPR iterator emplace(const_iterator __position, _Args&&... __args); @@ -1698,6 +1813,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * This function will insert a copy of the given value before the * specified location. */ + _GLIBCXX26_CONSTEXPR iterator insert(const_iterator __position, const value_type& __x); #else @@ -1724,6 +1840,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * This function will insert a copy of the given rvalue before the * specified location. */ + _GLIBCXX26_CONSTEXPR iterator insert(const_iterator __position, value_type&& __x) { return emplace(__position, std::move(__x)); } @@ -1738,6 +1855,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * initializer_list @a __l into the %deque before the location * specified by @a __p. This is known as <em>list insert</em>. */ + _GLIBCXX26_CONSTEXPR iterator insert(const_iterator __p, initializer_list<value_type> __l) { @@ -1757,6 +1875,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * This function will insert a specified number of copies of the given * data before the location specified by @a __position. */ + _GLIBCXX26_CONSTEXPR iterator insert(const_iterator __position, size_type __n, const value_type& __x) { @@ -1793,6 +1912,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ template<typename _InputIterator, typename = std::_RequireInputIter<_InputIterator>> + _GLIBCXX26_CONSTEXPR iterator insert(const_iterator __position, _InputIterator __first, _InputIterator __last) @@ -1834,6 +1954,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @since C++23 */ template<__detail::__container_compatible_range<_Tp> _Rg> + _GLIBCXX26_CONSTEXPR iterator insert_range(const_iterator __pos, _Rg&& __rg); @@ -1843,6 +1964,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @since C++23 */ template<__detail::__container_compatible_range<_Tp> _Rg> + _GLIBCXX26_CONSTEXPR void prepend_range(_Rg&& __rg); @@ -1852,6 +1974,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @since C++23 */ template<__detail::__container_compatible_range<_Tp> _Rg> + _GLIBCXX26_CONSTEXPR void append_range(_Rg&& __rg); #endif // containers_ranges @@ -1871,6 +1994,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ iterator #if __cplusplus >= 201103L + _GLIBCXX26_CONSTEXPR erase(const_iterator __position) #else erase(iterator __position) @@ -1895,6 +2019,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ iterator #if __cplusplus >= 201103L + _GLIBCXX26_CONSTEXPR erase(const_iterator __first, const_iterator __last) #else erase(iterator __first, iterator __last) @@ -1912,6 +2037,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * * Whether the allocators are swapped depends on the allocator traits. */ + // TODO: I don't know if we should poke this. + _GLIBCXX26_CONSTEXPR void swap(deque& __x) _GLIBCXX_NOEXCEPT { @@ -1930,6 +2057,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * pointed-to memory is not touched in any way. Managing the pointer is * the user's responsibility. */ + _GLIBCXX26_CONSTEXPR void clear() _GLIBCXX_NOEXCEPT { _M_erase_at_end(begin()); } @@ -1962,6 +2090,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } #endif + _GLIBCXX26_CONSTEXPR static size_t _S_check_init_len(size_t __n, const allocator_type& __a) { @@ -1971,6 +2100,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER return __n; } + _GLIBCXX26_CONSTEXPR static size_type _S_max_size(const _Tp_alloc_type& __a) _GLIBCXX_NOEXCEPT { @@ -1992,12 +2122,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * push_back on each value from the iterator. */ template<typename _InputIterator> + _GLIBCXX26_CONSTEXPR void _M_range_initialize(_InputIterator __first, _InputIterator __last, std::input_iterator_tag); // called by the second initialize_dispatch above template<typename _ForwardIterator> + _GLIBCXX26_CONSTEXPR void _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last, std::forward_iterator_tag); @@ -2013,11 +2145,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * This function is called only when the user provides an explicit size * (with or without an explicit exemplar value). */ + _GLIBCXX26_CONSTEXPR void _M_fill_initialize(const value_type& __value); #if __cplusplus >= 201103L // called by deque(n). + _GLIBCXX26_CONSTEXPR void _M_default_initialize(); #endif @@ -2093,14 +2227,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER void _M_push_front_aux(const value_type&); #else template<typename... _Args> + _GLIBCXX26_CONSTEXPR void _M_push_back_aux(_Args&&... __args); template<typename... _Args> + _GLIBCXX26_CONSTEXPR void _M_push_front_aux(_Args&&... __args); #endif + _GLIBCXX26_CONSTEXPR void _M_pop_back_aux(); + _GLIBCXX26_CONSTEXPR void _M_pop_front_aux(); ///@} @@ -2132,22 +2270,26 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // insert [__first, __last) at the front, assumes distance(__first, __last) is n template<typename _InputIterator, typename _Sentinel> + _GLIBCXX26_CONSTEXPR void _M_range_prepend(_InputIterator __first, _Sentinel __last, size_type __n); // insert [__first, __last) at the back, assumes distance(__first, __last) is n template<typename _InputIterator, typename _Sentinel> + _GLIBCXX26_CONSTEXPR void _M_range_append(_InputIterator __first, _Sentinel __last, size_type __n); // called by the second insert_dispatch above template<typename _InputIterator> + _GLIBCXX26_CONSTEXPR void _M_range_insert_aux(iterator __pos, _InputIterator __first, _InputIterator __last, std::input_iterator_tag); // called by the second insert_dispatch above template<typename _ForwardIterator> + _GLIBCXX26_CONSTEXPR void _M_range_insert_aux(iterator __pos, _ForwardIterator __first, _ForwardIterator __last, std::forward_iterator_tag); @@ -2155,6 +2297,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // Called by insert(p,n,x), and the range insert when it turns out to be // the same thing. Can use fill functions in optimal situations, // otherwise passes off to insert_aux(p,n,x). + _GLIBCXX26_CONSTEXPR void _M_fill_insert(iterator __pos, size_type __n, const value_type& __x); @@ -2163,11 +2306,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER iterator _M_insert_aux(iterator __pos, const value_type& __x); #else + _GLIBCXX26_CONSTEXPR iterator _M_insert_aux(iterator __pos, const value_type& __x) { return _M_emplace_aux(__pos, __x); } template<typename... _Args> + _GLIBCXX26_CONSTEXPR iterator _M_emplace_aux(iterator __pos, _Args&&... __args); #endif @@ -2186,16 +2331,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // Internal erase functions follow. + _GLIBCXX26_CONSTEXPR void _M_destroy_data_aux(iterator __first, iterator __last); // Called by ~deque(). // NB: Doesn't deallocate the nodes. template<typename _Alloc1> + _GLIBCXX26_CONSTEXPR void _M_destroy_data(iterator __first, iterator __last, const _Alloc1&) { _M_destroy_data_aux(__first, __last); } + _GLIBCXX26_CONSTEXPR void _M_destroy_data(iterator __first, iterator __last, const std::allocator<_Tp>&) @@ -2205,6 +2353,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } // Called by erase(q1, q2). + _GLIBCXX26_CONSTEXPR void _M_erase_at_begin(iterator __pos) { @@ -2215,6 +2364,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // Called by erase(q1, q2), resize(), clear(), _M_assign_aux, // _M_fill_assign, operator=. + _GLIBCXX26_CONSTEXPR void _M_erase_at_end(iterator __pos) { @@ -2224,23 +2374,28 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER this->_M_impl._M_finish = __pos; } + _GLIBCXX26_CONSTEXPR iterator _M_erase(iterator __pos); + _GLIBCXX26_CONSTEXPR iterator _M_erase(iterator __first, iterator __last); #if __cplusplus >= 201103L // Called by resize(sz). + _GLIBCXX26_CONSTEXPR void _M_default_append(size_type __n); + _GLIBCXX26_CONSTEXPR bool _M_shrink_to_fit(); #endif ///@{ /// Memory-handling helpers for the previous internal insert functions. + _GLIBCXX26_CONSTEXPR iterator _M_reserve_elements_at_front(size_type __n) { @@ -2251,6 +2406,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER return this->_M_impl._M_start - difference_type(__n); } + _GLIBCXX26_CONSTEXPR iterator _M_reserve_elements_at_back(size_type __n) { @@ -2261,9 +2417,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER return this->_M_impl._M_finish + difference_type(__n); } + _GLIBCXX26_CONSTEXPR void _M_new_elements_at_front(size_type __new_elements); + _GLIBCXX26_CONSTEXPR void _M_new_elements_at_back(size_type __new_elements); ///@} @@ -2277,6 +2435,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * actually add the nodes. Can invalidate _M_map pointers. * (And consequently, %deque iterators.) */ + _GLIBCXX26_CONSTEXPR void _M_reserve_map_at_back(size_type __nodes_to_add = 1) { @@ -2285,6 +2444,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_reallocate_map(__nodes_to_add, false); } + _GLIBCXX26_CONSTEXPR void _M_reserve_map_at_front(size_type __nodes_to_add = 1) { @@ -2293,6 +2453,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_reallocate_map(__nodes_to_add, true); } + _GLIBCXX26_CONSTEXPR void _M_reallocate_map(size_type __nodes_to_add, bool __add_at_front); ///@} @@ -2406,6 +2567,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ template<typename _Tp, typename _Alloc> _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR inline bool operator==(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y) { return __x.size() == __y.size() @@ -2425,6 +2587,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ template<typename _Tp, typename _Alloc> [[nodiscard]] + _GLIBCXX26_CONSTEXPR inline __detail::__synth3way_t<_Tp> operator<=>(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y) { @@ -2482,6 +2645,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER /// See std::deque::swap(). template<typename _Tp, typename _Alloc> + _GLIBCXX26_CONSTEXPR inline void swap(deque<_Tp,_Alloc>& __x, deque<_Tp,_Alloc>& __y) _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y))) diff --git a/libstdc++-v3/include/bits/stl_queue.h b/libstdc++-v3/include/bits/stl_queue.h index a3a8bc1f0ad..2ec1168c8a6 100644 --- a/libstdc++-v3/include/bits/stl_queue.h +++ b/libstdc++-v3/include/bits/stl_queue.h @@ -115,15 +115,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif template<typename _Tp1, typename _Seq1> + _GLIBCXX26_CONSTEXPR friend bool operator==(const queue<_Tp1, _Seq1>&, const queue<_Tp1, _Seq1>&); template<typename _Tp1, typename _Seq1> + _GLIBCXX26_CONSTEXPR friend bool operator<(const queue<_Tp1, _Seq1>&, const queue<_Tp1, _Seq1>&); #if __cpp_lib_three_way_comparison template<typename _Tp1, three_way_comparable _Seq1> + _GLIBCXX26_CONSTEXPR friend compare_three_way_result_t<_Seq1> operator<=>(const queue<_Tp1, _Seq1>&, const queue<_Tp1, _Seq1>&); #endif @@ -171,35 +174,43 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #else template<typename _Seq = _Sequence, typename _Requires = typename enable_if<is_default_constructible<_Seq>::value>::type> + _GLIBCXX26_CONSTEXPR queue() : c() { } + _GLIBCXX26_CONSTEXPR explicit queue(const _Sequence& __c) : c(__c) { } + _GLIBCXX26_CONSTEXPR explicit queue(_Sequence&& __c) : c(std::move(__c)) { } template<typename _Alloc, typename _Requires = _Uses<_Alloc>> + _GLIBCXX26_CONSTEXPR explicit queue(const _Alloc& __a) : c(__a) { } template<typename _Alloc, typename _Requires = _Uses<_Alloc>> + _GLIBCXX26_CONSTEXPR queue(const _Sequence& __c, const _Alloc& __a) : c(__c, __a) { } template<typename _Alloc, typename _Requires = _Uses<_Alloc>> + _GLIBCXX26_CONSTEXPR queue(_Sequence&& __c, const _Alloc& __a) : c(std::move(__c), __a) { } template<typename _Alloc, typename _Requires = _Uses<_Alloc>> + _GLIBCXX26_CONSTEXPR queue(const queue& __q, const _Alloc& __a) : c(__q.c, __a) { } template<typename _Alloc, typename _Requires = _Uses<_Alloc>> + _GLIBCXX26_CONSTEXPR queue(queue&& __q, const _Alloc& __a) : c(std::move(__q.c), __a) { } #endif @@ -207,12 +218,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #ifdef __glibcxx_adaptor_iterator_pair_constructor // C++ >= 23 && HOSTED template<typename _InputIterator, typename = _RequireInputIter<_InputIterator>> + _GLIBCXX26_CONSTEXPR queue(_InputIterator __first, _InputIterator __last) : c(__first, __last) { } template<typename _InputIterator, typename _Alloc, typename = _RequireInputIter<_InputIterator>, typename = _Uses<_Alloc>> + _GLIBCXX26_CONSTEXPR queue(_InputIterator __first, _InputIterator __last, const _Alloc& __a) : c(__first, __last, __a) { } #endif @@ -223,6 +236,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @since C++23 */ template<__detail::__container_compatible_range<_Tp> _Rg> + _GLIBCXX26_CONSTEXPR queue(from_range_t, _Rg&& __rg) : c(ranges::to<_Sequence>(std::forward<_Rg>(__rg))) { } @@ -233,6 +247,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION */ template<__detail::__container_compatible_range<_Tp> _Rg, typename _Alloc> + _GLIBCXX26_CONSTEXPR queue(from_range_t, _Rg&& __rg, const _Alloc& __a) : c(ranges::to<_Sequence>(std::forward<_Rg>(__rg), __a)) { } @@ -241,12 +256,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /** * Returns true if the %queue is empty. */ - _GLIBCXX_NODISCARD bool + _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR + bool empty() const { return c.empty(); } /** Returns the number of elements in the %queue. */ _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR size_type size() const { return c.size(); } @@ -256,6 +274,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * element of the %queue. */ _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR reference front() { @@ -268,6 +287,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * element of the %queue. */ _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR const_reference front() const { @@ -280,6 +300,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * element of the %queue. */ _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR reference back() { @@ -292,6 +313,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * element of the %queue. */ _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR const_reference back() const { @@ -308,17 +330,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * to it. The time complexity of the operation depends on the * underlying sequence. */ + _GLIBCXX26_CONSTEXPR void push(const value_type& __x) { c.push_back(__x); } #if __cplusplus >= 201103L + _GLIBCXX26_CONSTEXPR void push(value_type&& __x) { c.push_back(std::move(__x)); } #if __cplusplus > 201402L template<typename... _Args> + _GLIBCXX26_CONSTEXPR decltype(auto) emplace(_Args&&... __args) { return c.emplace_back(std::forward<_Args>(__args)...); } @@ -332,6 +357,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __glibcxx_containers_ranges // C++ >= 23 template<__detail::__container_compatible_range<_Tp> _Rg> + _GLIBCXX26_CONSTEXPR void push_range(_Rg&& __rg) { @@ -353,6 +379,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * data is needed, it should be retrieved before pop() is * called. */ + _GLIBCXX26_CONSTEXPR void pop() { @@ -361,6 +388,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } #if __cplusplus >= 201103L + _GLIBCXX26_CONSTEXPR void swap(queue& __q) #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 @@ -430,6 +458,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION */ template<typename _Tp, typename _Seq> _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR inline bool operator==(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y) { return __x.c == __y.c; } @@ -449,6 +478,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION */ template<typename _Tp, typename _Seq> _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR inline bool operator<(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y) { return __x.c < __y.c; } @@ -456,6 +486,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Based on operator== template<typename _Tp, typename _Seq> _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR inline bool operator!=(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y) { return !(__x == __y); } @@ -463,6 +494,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Based on operator< template<typename _Tp, typename _Seq> _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR inline bool operator>(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y) { return __y < __x; } @@ -470,6 +502,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Based on operator< template<typename _Tp, typename _Seq> _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR inline bool operator<=(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y) { return !(__y < __x); } @@ -477,6 +510,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Based on operator< template<typename _Tp, typename _Seq> _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR inline bool operator>=(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y) { return !(__x < __y); } @@ -484,6 +518,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cpp_lib_three_way_comparison template<typename _Tp, three_way_comparable _Seq> [[nodiscard]] + _GLIBCXX26_CONSTEXPR inline compare_three_way_result_t<_Seq> operator<=>(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y) { return __x.c <=> __y.c; } @@ -491,6 +526,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus >= 201103L template<typename _Tp, typename _Seq> + _GLIBCXX26_CONSTEXPR inline #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 // Constrained free swap overload, see p0185r1 @@ -607,22 +643,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Seq = _Sequence, typename _Requires = typename enable_if<__and_<is_default_constructible<_Compare>, is_default_constructible<_Seq>>::value>::type> + _GLIBCXX26_CONSTEXPR priority_queue() : c(), comp() { } + _GLIBCXX26_CONSTEXPR explicit priority_queue(const _Compare& __x, const _Sequence& __s) : c(__s), comp(__x) { std::make_heap(c.begin(), c.end(), comp); } + _GLIBCXX26_CONSTEXPR explicit priority_queue(const _Compare& __x, _Sequence&& __s = _Sequence()) : c(std::move(__s)), comp(__x) { std::make_heap(c.begin(), c.end(), comp); } + _GLIBCXX26_CONSTEXPR priority_queue(const priority_queue&) = default; + _GLIBCXX26_CONSTEXPR priority_queue& operator=(const priority_queue&) = default; + _GLIBCXX26_CONSTEXPR priority_queue(priority_queue&& __q) noexcept(__and_<is_nothrow_move_constructible<_Sequence>, is_nothrow_move_constructible<_Compare>>::value) @@ -641,32 +683,38 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template<typename _Alloc, typename _Requires = _Uses<_Alloc>> + _GLIBCXX26_CONSTEXPR explicit priority_queue(const _Alloc& __a) : c(__a), comp() { } template<typename _Alloc, typename _Requires = _Uses<_Alloc>> + _GLIBCXX26_CONSTEXPR priority_queue(const _Compare& __x, const _Alloc& __a) : c(__a), comp(__x) { } // _GLIBCXX_RESOLVE_LIB_DEFECTS // 2537. Constructors [...] taking allocators should call make_heap template<typename _Alloc, typename _Requires = _Uses<_Alloc>> + _GLIBCXX26_CONSTEXPR priority_queue(const _Compare& __x, const _Sequence& __c, const _Alloc& __a) : c(__c, __a), comp(__x) { std::make_heap(c.begin(), c.end(), comp); } template<typename _Alloc, typename _Requires = _Uses<_Alloc>> + _GLIBCXX26_CONSTEXPR priority_queue(const _Compare& __x, _Sequence&& __c, const _Alloc& __a) : c(std::move(__c), __a), comp(__x) { std::make_heap(c.begin(), c.end(), comp); } template<typename _Alloc, typename _Requires = _Uses<_Alloc>> + _GLIBCXX26_CONSTEXPR priority_queue(const priority_queue& __q, const _Alloc& __a) : c(__q.c, __a), comp(__q.comp) { } template<typename _Alloc, typename _Requires = _Uses<_Alloc>> + _GLIBCXX26_CONSTEXPR priority_queue(priority_queue&& __q, const _Alloc& __a) : c(std::move(__q.c), __a), comp(std::move(__q.comp)) { __q.c.clear(); } @@ -702,6 +750,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // 3529. priority_queue(first, last) should construct c with (first, last) template<typename _InputIterator, typename = std::_RequireInputIter<_InputIterator>> + _GLIBCXX26_CONSTEXPR priority_queue(_InputIterator __first, _InputIterator __last, const _Compare& __x = _Compare()) : c(__first, __last), comp(__x) @@ -711,6 +760,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // 3522. Missing requirement on InputIterator template parameter template<typename _InputIterator, typename = std::_RequireInputIter<_InputIterator>> + _GLIBCXX26_CONSTEXPR priority_queue(_InputIterator __first, _InputIterator __last, const _Compare& __x, const _Sequence& __s) : c(__s), comp(__x) @@ -722,6 +772,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _InputIterator, typename = std::_RequireInputIter<_InputIterator>> + _GLIBCXX26_CONSTEXPR priority_queue(_InputIterator __first, _InputIterator __last, const _Compare& __x, _Sequence&& __s) : c(std::move(__s)), comp(__x) @@ -736,6 +787,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _InputIterator, typename _Alloc, typename = std::_RequireInputIter<_InputIterator>, typename _Requires = _Uses<_Alloc>> + _GLIBCXX26_CONSTEXPR priority_queue(_InputIterator __first, _InputIterator __last, const _Alloc& __alloc) : c(__first, __last, __alloc), comp() @@ -744,6 +796,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _InputIterator, typename _Alloc, typename = std::_RequireInputIter<_InputIterator>, typename _Requires = _Uses<_Alloc>> + _GLIBCXX26_CONSTEXPR priority_queue(_InputIterator __first, _InputIterator __last, const _Compare& __x, const _Alloc& __alloc) : c(__first, __last, __alloc), comp(__x) @@ -752,6 +805,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _InputIterator, typename _Alloc, typename = std::_RequireInputIter<_InputIterator>, typename _Requires = _Uses<_Alloc>> + _GLIBCXX26_CONSTEXPR priority_queue(_InputIterator __first, _InputIterator __last, const _Compare& __x, const _Sequence& __s, const _Alloc& __alloc) @@ -764,6 +818,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _InputIterator, typename _Alloc, typename _Requires = _Uses<_Alloc>> + _GLIBCXX26_CONSTEXPR priority_queue(_InputIterator __first, _InputIterator __last, const _Compare& __x, _Sequence&& __s, const _Alloc& __alloc) @@ -783,18 +838,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @{ */ template<__detail::__container_compatible_range<_Tp> _Rg> + _GLIBCXX26_CONSTEXPR priority_queue(from_range_t, _Rg&& __rg, const _Compare& __x = _Compare()) : c(ranges::to<_Sequence>(std::forward<_Rg>(__rg))), comp(__x) { std::make_heap(c.begin(), c.end(), comp); } template<__detail::__container_compatible_range<_Tp> _Rg, typename _Alloc> + _GLIBCXX26_CONSTEXPR priority_queue(from_range_t, _Rg&& __rg, const _Compare& __x, const _Alloc& __a) : c(ranges::to<_Sequence>(std::forward<_Rg>(__rg), __a)), comp(__x) { std::make_heap(c.begin(), c.end(), comp); } template<__detail::__container_compatible_range<_Tp> _Rg, typename _Alloc> + _GLIBCXX26_CONSTEXPR priority_queue(from_range_t, _Rg&& __rg, const _Alloc& __a) : c(ranges::to<_Sequence>(std::forward<_Rg>(__rg), __a)), comp() { std::make_heap(c.begin(), c.end(), comp); } @@ -804,12 +862,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /** * Returns true if the %queue is empty. */ - _GLIBCXX_NODISCARD bool + _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR + bool empty() const { return c.empty(); } /** Returns the number of elements in the %queue. */ _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR size_type size() const { return c.size(); } @@ -819,6 +880,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * element of the %queue. */ _GLIBCXX_NODISCARD + _GLIBCXX26_CONSTEXPR const_reference top() const { @@ -834,6 +896,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * The time complexity of the operation depends on the underlying * sequence. */ + _GLIBCXX26_CONSTEXPR void push(const value_type& __x) { @@ -842,6 +905,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } #if __cplusplus >= 201103L + _GLIBCXX26_CONSTEXPR void push(value_type&& __x) { @@ -850,6 +914,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template<typename... _Args> + _GLIBCXX26_CONSTEXPR void emplace(_Args&&... __args) { @@ -860,6 +925,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __glibcxx_containers_ranges // C++ >= 23 template<__detail::__container_compatible_range<_Tp> _Rg> + _GLIBCXX26_CONSTEXPR void push_range(_Rg&& __rg) { @@ -882,6 +948,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * data is needed, it should be retrieved before pop() is * called. */ + _GLIBCXX26_CONSTEXPR void pop() { @@ -891,6 +958,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } #if __cplusplus >= 201103L + _GLIBCXX26_CONSTEXPR void swap(priority_queue& __pq) noexcept(__and_< @@ -959,6 +1027,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus >= 201103L template<typename _Tp, typename _Sequence, typename _Compare> + _GLIBCXX26_CONSTEXPR inline #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 // Constrained free swap overload, see p0185r1 diff --git a/libstdc++-v3/include/bits/stl_uninitialized.h b/libstdc++-v3/include/bits/stl_uninitialized.h index 351c3a17457..6719c558a40 100644 --- a/libstdc++-v3/include/bits/stl_uninitialized.h +++ b/libstdc++-v3/include/bits/stl_uninitialized.h @@ -987,6 +987,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if _GLIBCXX_HOSTED template<typename _ForwardIterator, typename _Tp> + _GLIBCXX26_CONSTEXPR inline void __uninitialized_default_a(_ForwardIterator __first, _ForwardIterator __last, diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def index dbe2cb8f175..b7fd4ec8bd2 100644 --- a/libstdc++-v3/include/bits/version.def +++ b/libstdc++-v3/include/bits/version.def @@ -2069,6 +2069,22 @@ ftms = { }; }; +ftms = { + name = constexpr_queue; + values = { + v = 202502; + cxxmin = 26; + }; +}; + +ftms = { + name = constexpr_deque; + values = { + v = 202502; + cxxmin = 26; + }; +}; + // Standard test specifications. stds[97] = ">= 199711L"; stds[03] = ">= 199711L"; diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h index 7bb6016df68..96f08e580d2 100644 --- a/libstdc++-v3/include/bits/version.h +++ b/libstdc++-v3/include/bits/version.h @@ -2318,4 +2318,24 @@ #endif /* !defined(__cpp_lib_constexpr_exceptions) && defined(__glibcxx_want_constexpr_exceptions) */ #undef __glibcxx_want_constexpr_exceptions +#if !defined(__cpp_lib_constexpr_queue) +# if (__cplusplus > 202302L) +# define __glibcxx_constexpr_queue 202502L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_constexpr_queue) +# define __cpp_lib_constexpr_queue 202502L +# endif +# endif +#endif /* !defined(__cpp_lib_constexpr_queue) && defined(__glibcxx_want_constexpr_queue) */ +#undef __glibcxx_want_constexpr_queue + +#if !defined(__cpp_lib_constexpr_deque) +# if (__cplusplus > 202302L) +# define __glibcxx_constexpr_deque 202502L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_constexpr_deque) +# define __cpp_lib_constexpr_deque 202502L +# endif +# endif +#endif /* !defined(__cpp_lib_constexpr_deque) && defined(__glibcxx_want_constexpr_deque) */ +#undef __glibcxx_want_constexpr_deque + #undef __glibcxx_want_all diff --git a/libstdc++-v3/include/std/deque b/libstdc++-v3/include/std/deque index 2badab80a6d..c8a3649d643 100644 --- a/libstdc++-v3/include/std/deque +++ b/libstdc++-v3/include/std/deque @@ -75,6 +75,7 @@ #define __glibcxx_want_containers_ranges #define __glibcxx_want_erase_if #define __glibcxx_want_nonmember_container_access +#define __glibcxx_want_constexpr_deque #include <bits/version.h> #ifdef _GLIBCXX_DEBUG @@ -101,6 +102,7 @@ namespace std _GLIBCXX_VISIBILITY(default) _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp, typename _Alloc, typename _Predicate> + _GLIBCXX26_CONSTEXPR inline typename deque<_Tp, _Alloc>::size_type erase_if(deque<_Tp, _Alloc>& __cont, _Predicate __pred) { @@ -122,6 +124,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp, typename _Alloc, typename _Up _GLIBCXX26_DEF_VAL_T(_Tp)> + _GLIBCXX26_CONSTEXPR inline typename deque<_Tp, _Alloc>::size_type erase(deque<_Tp, _Alloc>& __cont, const _Up& __value) { diff --git a/libstdc++-v3/include/std/queue b/libstdc++-v3/include/std/queue index 1b76088b31b..721ec4c5bef 100644 --- a/libstdc++-v3/include/std/queue +++ b/libstdc++-v3/include/std/queue @@ -63,6 +63,7 @@ #define __glibcxx_want_adaptor_iterator_pair_constructor #define __glibcxx_want_containers_ranges +#define __glibcxx_want_constexpr_queue #include <bits/version.h> #include <deque> diff --git a/libstdc++-v3/testsuite/23_containers/deque/constexpr.cc b/libstdc++-v3/testsuite/23_containers/deque/constexpr.cc new file mode 100644 index 00000000000..4689b04ee63 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/deque/constexpr.cc @@ -0,0 +1,266 @@ +// { dg-do compile { target c++26 } } + +#include <deque> + +#ifndef __cpp_lib_constexpr_deque +#error "Feature test macro for constexpr deque is missing in <deque>" +#elif __cpp_lib_constexpr_deque != 202502L +# error "Feature test macro for constexpr deque has wrong value in <deque>" +#endif + +#include <ranges> +#include <numeric> +#include <testsuite_hooks.h> + +template<typename T> +struct Alloc : std::allocator<T> +{ + using std::allocator<T>::allocator; + + int personality = 0; + constexpr explicit Alloc (int p) : personality(p) { } + + template<typename U> + constexpr Alloc(const Alloc<U>& a) : personality(a.personality) { } +}; + +constexpr bool ctor_tests() +{ + std::deque<int> dq1 {}; + + Alloc<int> alloc (6); + std::deque<int> dq2 (alloc); + std::deque<int> dq3 (4, alloc); + VERIFY( dq3.front() == 0 ); + VERIFY( dq3.size() == 4 ); + std::deque<int> dq4 (4, 5, alloc); + VERIFY( dq4.front() == 5 ); + VERIFY( dq4.size() == 4 ); + + auto rg = {2, 3, 5, 7}; + auto dq5 = std::deque(rg.begin(), rg.end()); + VERIFY( dq5.front() == 2 ); + VERIFY( dq5.back() == 7 ); + VERIFY( dq5.size() == 4 ); + + auto dq6 = std::deque<int>(std::from_range, rg); + VERIFY( dq6 == dq5 ); + + std::deque<int> dq7 (dq1); + VERIFY( dq7 == dq1 ); + std::deque<int>dq8 (std::move(dq1)); + VERIFY( dq8 == dq7 ); + + std::deque<int> dq9 (dq1, alloc); + std::deque<int> dq10 (std::move(dq1), alloc); + VERIFY ( dq9 == dq10 ); + std::deque<int> dq11 (rg, alloc); + VERIFY( dq11 == dq5 ); + + return true; +} + +static_assert(ctor_tests()); + +constexpr bool insert_tests() +{ + std::deque<int> dq1 {}; + + auto rg = {1, 2, 3, 4, 5}; + + dq1.insert(dq1.begin() , 1); + dq1.insert(dq1.end(), 2); + VERIFY( dq1.size() == 2 ); + VERIFY( dq1.front() == 1 ); + VERIFY( dq1.back() == 2 ); + + dq1.insert(dq1.end(), 1, 3); + + dq1.insert(dq1.end(), rg.begin() + 3, rg.end()); + + VERIFY( dq1[0] == 1 ); + VERIFY( dq1[1] == 2 ); + VERIFY( dq1[2] == 3 ); + VERIFY( dq1[3] == 4 ); + VERIFY( dq1[4] == 5 ); + dq1.clear(); + + dq1.insert(dq1.begin(), rg.begin(), rg.end()); + VERIFY( dq1[0] == 1 ); + VERIFY( dq1[1] == 2 ); + VERIFY( dq1[2] == 3 ); + VERIFY( dq1[3] == 4 ); + VERIFY( dq1[4] == 5 ); + + dq1.insert_range(dq1.end(), rg); + VERIFY( dq1[5] == 1 ); + VERIFY( dq1[6] == 2 ); + VERIFY( dq1[7] == 3 ); + VERIFY( dq1[8] == 4 ); + VERIFY( dq1[9] == 5 ); + + std::deque<int> dq2 {2, 3, 5, 7}; + dq2.erase(dq2.begin()); + VERIFY( dq2.size() == 3 ); + dq2.clear(); + VERIFY( dq2.size() == 0); + VERIFY( dq2.empty() ); + + std::deque<int> dq3, dq4; + dq3.insert_range(dq3.begin(), rg); + dq4.append_range(rg); + VERIFY( dq3 == dq4 ); + dq3.erase(dq3.begin(), dq3.end()); + dq3.prepend_range(rg); + VERIFY( dq3 == dq4 ); + + + struct S { + int foo; + constexpr S (int i, int j) : foo{i + j} {} + }; + std::deque<S> dq5 {}; + dq5.emplace(dq5.end(), 0, 1); + const S& s1 = dq5.emplace_back(1, 1); + const S& s2 = dq5.emplace_front(2, 1); + VERIFY( dq5.front().foo == 3 ); + VERIFY( dq5.back().foo == 2 ); + VERIFY( dq5[1].foo == 1 ); + + std::deque<int> dq6 {2, 3}; + dq6.push_front(1); + dq6.push_back(4); + VERIFY( dq6.front() == 1); + VERIFY( dq6.back() == 4 ); + dq6.pop_front(); + dq6.pop_back(); + + std::deque<int> dq7 {1, 2}; + dq7.resize(4); + VERIFY( dq7.back() == 0 ); + dq7.resize(2); + VERIFY( dq7.front() == 1 ); + VERIFY( dq7.back() == 2 ); + dq7.clear(); + dq7.resize(2); + VERIFY( dq7.front() == 0 ); + VERIFY( dq7.back() == 0 ); + + std::deque<int> dq8 {1, 4}; + dq8.swap(dq6); + VERIFY( dq6.front() == 1 ); + VERIFY( dq6.back() == 4 ); + VERIFY( dq8.front() == 2 ); + VERIFY( dq8.back() == 3 ); + + return true; +} + +static_assert(insert_tests()); + +constexpr bool iterators_tests() +{ + std::deque<int> dq0 {}; + VERIFY( dq0.begin() == dq0.end() ); + dq0.resize(1); + VERIFY( dq0.begin() != dq0.end() ); + dq0.resize(2); + VERIFY( dq0.begin() != dq0.end() ); + VERIFY( dq0.cbegin() == dq0.begin() ); + VERIFY( dq0.crbegin() == dq0.rbegin() ); + VERIFY( dq0.cend() == dq0.end() ); + VERIFY( dq0.crend() == dq0.rend() ); + + auto it = dq0.begin(); + VERIFY( it[0] == 0 ); + VERIFY( &*it == &dq0.front() ); + VERIFY( &it[1] == &dq0[1] ); + VERIFY( it++ == dq0.begin() ); + VERIFY( ++it == dq0.end() ); + VERIFY( (it - 2) == dq0.begin() ); + VERIFY( (it - dq0.begin()) == 2 ); + it -= 2; + it += 1; + VERIFY( (it + 1) == dq0.end() ); + VERIFY( (1 + it) == dq0.end() ); + it = it + 1; + auto it2 = dq0.begin(); + std::swap(it, it2); + VERIFY( it == dq0.begin() ); + VERIFY( it2 == dq0.end() ); + + auto rit = dq0.rbegin(); + VERIFY( rit[0] == 0 ); + VERIFY( &*rit == &dq0.back() ); + VERIFY( &rit[1] == &dq0[0] ); + VERIFY( rit++ == dq0.rbegin() ); + VERIFY( ++rit == dq0.rend() ); + VERIFY( (rit - 2) == dq0.rbegin() ); + VERIFY( (rit - dq0.rbegin()) == 2 ); + rit -= 2; + rit += 1; + VERIFY( (rit + 1) == dq0.rend() ); + VERIFY( (1 + rit) == dq0.rend() ); + rit = rit + 1; + auto rit2 = dq0.rbegin(); + std::swap(rit, rit2); + VERIFY( rit == dq0.rbegin() ); + VERIFY( rit2 == dq0.rend() ); + + return true; +} + +static_assert(iterators_tests()); + +constexpr bool capacity_tests() +{ + std::deque<int> dq0 {}; + VERIFY( dq0.empty() ); + VERIFY( dq0.max_size() ); + dq0.push_front(0); + VERIFY( dq0.size() == 1 ); + dq0.erase(dq0.begin()); + dq0.shrink_to_fit(); + + return true; +} + +static_assert(capacity_tests()); + +constexpr bool nonmember_tests() +{ + std::deque<int> dq0 {0, 1}; + std::deque<int> dq1 {0, 1}; + + VERIFY( (dq0 == dq1) == true ); + VERIFY( (dq0 != dq1) == false ); + VERIFY( (dq0 <= dq1) == true ); + VERIFY( (dq0 >= dq1) == true ); + VERIFY( (dq0 < dq1) == false ); + VERIFY( (dq0 > dq1) == false ); + VERIFY( (dq0 <=> dq1) == 0 ); + VERIFY( (dq0 <=> dq1) <= 0 ); + VERIFY( (dq0 <=> dq1) >= 0 ); + + std::deque<int> dq2 {2, 4}; + std::swap(dq1, dq2); + + VERIFY( (dq0 == dq1) == false ); + VERIFY( (dq0 != dq1) == true ); + VERIFY( (dq0 <= dq1) == true ); + VERIFY( (dq0 >= dq1) == false ); + VERIFY( (dq0 < dq1) == true ); + VERIFY( (dq0 > dq1) == false ); + VERIFY( (dq0 <=> dq1) != 0 ); + VERIFY( (dq0 <=> dq1) <= 0 ); + VERIFY( (dq0 <=> dq1) < 0 ); + + std::erase(dq0, 0); + VERIFY( dq0.front() == 1 ); + + std::erase_if(dq1, [](int x) { return x % 2 == 0; }); + VERIFY( dq1.empty() ); + return true; +} + +static_assert(nonmember_tests()); diff --git a/libstdc++-v3/testsuite/23_containers/priority_queue/constexpr.cc b/libstdc++-v3/testsuite/23_containers/priority_queue/constexpr.cc new file mode 100644 index 00000000000..ae4529a9aa8 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/priority_queue/constexpr.cc @@ -0,0 +1,233 @@ +// { dg-do compile { target c++26 } } + +#include <queue> + +#ifndef __cpp_lib_constexpr_queue +#error "Feature test macro for constexpr queue is missing in <queue>" +#elif __cpp_lib_constexpr_queue != 202502L +# error "Feature test macro for constexpr queue has wrong value in <queue>" +#endif + +#include <ranges> +#include <functional> +#include <vector> +#include <numeric> +#include <testsuite_hooks.h> + +template<typename T> +struct Alloc : std::allocator<T> +{ + using std::allocator<T>::allocator; + + int personality = 0; + constexpr explicit Alloc (int p) : personality(p) { } + + template<typename U> + constexpr Alloc(const Alloc<U>& a) : personality(a.personality) { } +}; + +constexpr bool ctor_tests() +{ + auto rg = {2, 3, 5, 7}; + std::vector<int> v0 {std::from_range, rg}; + + std::priority_queue<int> pq1; + VERIFY( pq1.size() == 0 && pq1.empty() ); + + std::priority_queue<int> pq2 {std::less<int>()}; + VERIFY( pq2.size() == 0 && pq2.empty() ); + + std::priority_queue<int> pq3 {std::less<int>(), v0}; + VERIFY( pq3.size() == 4 && pq3.top() == 7 ); + + std::priority_queue<int> pq4 {std::less<int>(), std::move(v0)}; + VERIFY( pq4.size() == 4 && pq4.top() == 7 ); + + std::priority_queue<int> pq5 (pq3); + VERIFY( pq5.top() == pq3.top() ); + VERIFY( pq5.size() == pq3.size() ); + + std::priority_queue<int> pq6 (std::move(pq3)); + VERIFY( pq6.top() == pq5.top() ); + VERIFY( pq6.size() == pq5.size() ); + + std::vector<int> v1 {}; + + std::priority_queue<int> pq10(std::begin(rg), std::end(rg), + std::less<int>()); + VERIFY( pq10.size() == std::size(rg) ); + VERIFY( pq10.top() == 7 ); + pq10.pop(); + VERIFY( pq10.top() == 5 ); + pq10.pop(); + VERIFY( pq10.top() == 3 ); + pq10.pop(); + VERIFY( pq10.top() == 2 ); + pq10.pop(); + + std::priority_queue<int> pq11(std::begin(rg), std::end(rg), + std::less<int>(), v1); + VERIFY( pq11.size() == std::size(rg)); + VERIFY( pq11.top() == 7 ); + pq11.pop(); + VERIFY( pq11.top() == 5 ); + pq11.pop(); + VERIFY( pq11.top() == 3 ); + pq11.pop(); + VERIFY( pq11.top() == 2 ); + pq11.pop(); + + std::priority_queue<int> pq12(std::begin(rg), std::end(rg), + std::less<int>(), std::move(v1)); + VERIFY( pq12.size() == std::size(rg)); + VERIFY( pq12.top() == 7 ); + pq12.pop(); + VERIFY( pq12.top() == 5 ); + pq12.pop(); + VERIFY( pq12.top() == 3 ); + pq12.pop(); + VERIFY( pq12.top() == 2 ); + pq12.pop(); + + auto pq13 = std::priority_queue<int>(std::from_range, std::ranges::views::iota(0, 7), std::less<int>()); + VERIFY( pq13.size() == 7 ); + + return true; +} + +static_assert( ctor_tests() ); + +constexpr bool alloc_aware_ctor_tests() +{ + std::allocator<int> alloc; + auto rg = {1, 0}; + constexpr std::vector<int> v0 {}; + std::priority_queue<int> pq14 (alloc); + + std::priority_queue<int> pq15 (std::less<int>(), alloc); + pq15.push(0); + pq15.push(1); + VERIFY( pq15.top() == 1 ); + + std::priority_queue<int> pq16 (std::less<int>(), v0, alloc); + pq16.push(0); + pq16.push(1); + VERIFY( pq16.top() == 1 ); + + std::priority_queue<int> pq17 (std::less<int>(), std::move(v0), alloc); + pq17.push(0); + pq17.push(1); + VERIFY( pq17.top() == 1 ); + + std::priority_queue<int> pq18 (pq17, alloc); + VERIFY( pq18.size() == pq17.size()); + VERIFY( pq18.top() == 1 ); + + std::priority_queue<int> pq19 (std::move(pq17), alloc); + VERIFY( pq19.size() == pq18.size() ); + VERIFY( pq18.top() == 1 ); + + constexpr std::vector<int> v1 {}; + + std::priority_queue<int> pq20(std::begin(rg), std::end(rg), + std::less<int>(), alloc); + VERIFY( pq20.top() == 1 ); + VERIFY( pq20.size() == std::size(rg) ); + + std::priority_queue<int> pq21(std::begin(rg), std::end(rg), + std::less<int>(), v1, alloc); + VERIFY( pq21.top() == 1 ); + VERIFY( pq21.size() == std::size(rg) ); + + std::priority_queue<int> pq22(std::begin(rg), std::end(rg), + std::less<int>(), std::move(v1), alloc); + VERIFY( pq21.top() == 1 ); + VERIFY( pq22.size() == std::size(rg) ); + + auto pq23 = std::priority_queue<int>(std::from_range, std::ranges::views::iota(0, 7), alloc); + VERIFY( pq23.size() == 7 ); + + auto pq24 = std::priority_queue<int>(std::from_range, std::ranges::views::iota(0, 7), std::less<int>(), alloc); + VERIFY( pq24.size() == 7 ); + + return true; +} + +static_assert( alloc_aware_ctor_tests() ); + +constexpr bool push_and_pop_test() +{ + std::priority_queue<int> a; + a.push(1); + a.pop(); + + return true; +} + +static_assert( push_and_pop_test() ); + +constexpr bool top_test () +{ + std::priority_queue<int> a; + a.push(2); + a.push(4); + VERIFY( a.top() == 4 ); + + return true; +} + +static_assert( top_test() ); + +constexpr int push_range_test() +{ + std::priority_queue<int> pq; + const auto rg = {2, 3, 5, 7}; + pq.push_range(rg); + VERIFY( pq.size() == 4); + VERIFY( pq.top() == 7); + pq.pop(); + VERIFY( pq.top() == 5); + pq.pop(); + VERIFY( pq.top() == 3); + pq.pop(); + VERIFY( pq.top() == 2); + pq.pop(); + VERIFY( pq.size() == 0); + return true; +} + +static_assert( push_range_test() ); + +constexpr int swap_test() +{ + std::priority_queue<int> a,b; + a.push(2); + b.push(4); + std::swap(a, b); + VERIFY( a.top() == 4 ); + VERIFY( b.top() == 2 ); + return true; +} + +static_assert (swap_test()); + +struct S +{ + int foo; + constexpr S(int i, int j) : foo{i + j} {} + constexpr friend bool operator< (S const &x, S const &y) { return x.foo < y.foo; } +}; + +constexpr bool emplace_test() +{ + std::priority_queue<S> pq; + pq.emplace(0, 0); + pq.emplace(1, 0); + VERIFY( pq.size() == 2 ); + VERIFY( pq.top().foo == 1 ); + pq.pop(); + VERIFY ( pq.top().foo == 0 ); + return true; +} + +static_assert( emplace_test() ); diff --git a/libstdc++-v3/testsuite/23_containers/queue/constexpr.cc b/libstdc++-v3/testsuite/23_containers/queue/constexpr.cc new file mode 100644 index 00000000000..8a00ba83c46 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/queue/constexpr.cc @@ -0,0 +1,194 @@ +// { dg-do compile { target c++26 } } + +#include <queue> + +#ifndef __cpp_lib_constexpr_queue +#error "Feature test macro for constexpr queue is missing in <queue>" +#elif __cpp_lib_constexpr_queue != 202502L +# error "Feature test macro for constexpr queue has wrong value in <queue>" +#endif + +#include <ranges> +#include <numeric> +#include <testsuite_hooks.h> + +template<typename T> +struct Alloc : std::allocator<T> +{ + using std::allocator<T>::allocator; + + int personality = 0; + constexpr explicit Alloc (int p) : personality(p) { } + + template<typename U> + constexpr Alloc(const Alloc<U>& a) : personality(a.personality) { } +}; + +constexpr bool ctor_tests() +{ + std::queue<int> q1; + VERIFY( q1.size() == 0 && q1.empty() ); + q1.push(1); + q1.push(2); + VERIFY( q1.size() == 2) ; + + std::queue<int> q2 (q1); + VERIFY( q2.size() == q1.size() ); + VERIFY( q2.front() == q1.front() ); + VERIFY( q2.back() == q1.back() ); + + std::queue<int> q3 (std::move(q2)); + VERIFY( q3.size() == q1.size() ); + VERIFY( q3.front() == q1.front() ); + VERIFY( q3.back() == q1.back() ); + VERIFY( q2.empty() ); + + std::allocator<int> alloc; + std::queue<int> q4 (alloc); + q4.push(1); + q4.push(2); + VERIFY( q4.size() == 2 ); + + std::queue<int> q5 (q4, alloc); + VERIFY( q5 == q4 ); + VERIFY( q5.size() == q4.size() ); + VERIFY( q5.front() == q4.front() ); + VERIFY( q5.back() == q4.back() ); + + std::queue<int> q6 (std::move(q5), alloc); + VERIFY( q6 == q4 ); + VERIFY( q6.size() == q4.size() ); + VERIFY( q5.empty() ); + + Alloc<int> aa(5); + std::queue<int> q7 (aa); + VERIFY( q7.size() == 0 ); + + int rg[4] = {2, 3, 5, 7}; + std::queue<int> q8(std::begin(rg), std::end(rg)); + VERIFY( q8.size() == std::size(rg)); + VERIFY( q8.front() == 2 ); + q8.pop(); + VERIFY( q8.front() == 3 ); + q8.pop(); + VERIFY( q8.front() == 5 ); + q8.pop(); + VERIFY( q8.front() == 7 ); + q8.pop(); + + std::queue<int> q9(std::begin(rg), std::end(rg), aa); + VERIFY( q9.size() == std::size(rg)); + VERIFY( q9.front() == 2 ); + q9.pop(); + VERIFY( q9.front() == 3 ); + q9.pop(); + VERIFY( q9.front() == 5 ); + q9.pop(); + VERIFY( q9.front() == 7 ); + q9.pop(); + + auto q10 = std::queue<int>(std::from_range, std::ranges::views::iota(0, 7)); + VERIFY( q10.size() == 7 ); + + auto q11 = std::queue<int>(std::from_range, std::ranges::views::iota(0, 7), alloc); + VERIFY( q11.size() == 7 ); + + auto q12 = std::queue<int>(std::from_range, std::ranges::views::iota(0, 7), aa); + VERIFY( q12.size() == 7 ); + + return true; +} + +static_assert( ctor_tests() ); + +constexpr bool push_and_pop_test() +{ + std::queue<int> a; + a.push(1); + a.pop(); + + return true; +} + +static_assert( push_and_pop_test() ); + +constexpr bool front_and_back_test() +{ + std::queue<int> a; + a.push(2); + a.push(4); + VERIFY ( a.front() == 2 && a.back() == 4); + return true; +} + +static_assert( front_and_back_test() ); + +constexpr int push_range_test() +{ + std::queue<int> a; + const auto rg = {2, 3, 5, 7}; + a.push_range(rg); + VERIFY( a.size() == 4 ); + VERIFY( a.front() == 2 ); + a.pop(); + VERIFY( a.front() == 3 ); + a.pop(); + VERIFY( a.front() == 5 ); + a.pop(); + VERIFY( a.front() == 7 ); + a.pop(); + VERIFY( a.size() == 0 ); + return true; +} + +static_assert (push_range_test()); + +constexpr int swap_test() +{ + std::queue<int> a,b; + a.push(1); + b.push(2); + std::swap(a, b); + VERIFY( a.front() == 2 ); + VERIFY( b.front() == 1 ); + return true; +} + +static_assert (swap_test()); + +struct S +{ + int foo; + constexpr S(int i, int j) : foo{i + j} {} +}; + +constexpr bool emplace_test() +{ + std::queue<S> a; + const S& s = a.emplace(196883, 1); + VERIFY ( a.size() == 1 ); + VERIFY ( a.front().foo == 196884 ); + return true; +} + +static_assert( emplace_test() ); + +constexpr bool operator_test() +{ + std::queue<int> a, b; + a.push(1); + b.push(1); + VERIFY ( a == b ); + VERIFY ( a <= b ); + VERIFY ( a >= b ); + b.pop(); + b.push(2); + VERIFY ( a < b ); + VERIFY ( !(a > b) ); + VERIFY ( a <= b ); + VERIFY ( !(a >= b) ); + VERIFY ( a != b ); + return true; +} + +static_assert( operator_test() ); -- 2.34.1