mirror of
https://gcc.gnu.org/git/gcc.git
synced 2026-02-22 12:00:03 -05:00
This patch implements formatter specializations for standard container adaptors (queue, priority_queue and stack) from P2286R8. To be able to access the protected `c` member, the adaptors befriend corresponding formatter specializations. Note that such specialization may be disable if the container is formattable, in such case specializations are unharmful. As in the case of previous commits, the signatures of the user-facing parse and format methods of the provided formatters deviate from the standard by constraining types of parameters: * _CharT is constrained __formatter::__char * basic_format_parse_context<_CharT> for parse argument * basic_format_context<_Out, _CharT> for format second argument The standard specifies all above as unconstrained types. In particular _CharT constrain, allow us to befriend all allowed specializations. Furthermore the standard specifies these formatters as delegating to formatter<ranges::ref_view<const? _Container>, charT>, which in turn delegates to range_formatter. This patch avoids one level of indirection, and dependency of ranges::ref_view. This is technically observable if user specializes formatter<std::ref_view<PD>> where PD is program defined container, but I do not think this is the case worth extra indirection. This patch also moves the formattable and it's dependencies to the formatfwd.h, so it can be used in adapters formatters, without including format header. The definition of _Iter_for is changed from alias to denoting back_insert_iterator<basic_string<_CharT>>, to struct with type nested typedef that points to same type, that is forward declared. PR libstdc++/109162 libstdc++-v3/ChangeLog: * include/bits/formatfwd.h (__format::__parsable_with) (__format::__formattable_with, __format::__formattable_impl) (__format::__has_debug_format, __format::__const_formattable_range) (__format::__maybe_const_range, __format::__maybe_const) (std::formattable): Moved from std/format. (__format::Iter_for, std::range_formatter): Forward declare. * include/bits/stl_queue.h (std::formatter): Forward declare. (std::queue, std::priority_queue): Befriend formatter specializations. * include/bits/stl_stack.h (std::formatter): Forward declare. (std::stack): Befriend formatter specializations. * include/std/format (__format::_Iter_for): Define as struct with (__format::__parsable_with, __format::__formattable_with) (__format::__formattable_impl, __format::__has_debug_format) (_format::__const_formattable_range, __format::__maybe_const_range) (__format::__maybe_const, std::formattable): Moved to bits/formatfwd.h. (std::range_formatter): Remove default argument specified in declaration in bits/formatfwd.h. * include/std/queue: Include bits/version.h before bits/stl_queue.h. (formatter<queue<_Tp, _Container, _Compare>, _CharT>) (formatter<priority_queue<_Tp, _Container, _Compare>, _CharT>): Define. * include/std/stack: Include bits/version.h before bits/stl_stack.h (formatter<stack<_Tp, _Container, _Compare>, _CharT>): Define. * testsuite/std/format/ranges/adaptors.cc: New test. Reviewed-by: Jonathan Wakely <jwakely@redhat.com> Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
985 lines
32 KiB
C++
985 lines
32 KiB
C++
// Queue implementation -*- C++ -*-
|
|
|
|
// Copyright (C) 2001-2025 Free Software Foundation, Inc.
|
|
//
|
|
// This file is part of the GNU ISO C++ Library. This library is free
|
|
// software; you can redistribute it and/or modify it under the
|
|
// terms of the GNU General Public License as published by the
|
|
// Free Software Foundation; either version 3, or (at your option)
|
|
// any later version.
|
|
|
|
// This library is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
|
|
// Under Section 7 of GPL version 3, you are granted additional
|
|
// permissions described in the GCC Runtime Library Exception, version
|
|
// 3.1, as published by the Free Software Foundation.
|
|
|
|
// You should have received a copy of the GNU General Public License and
|
|
// a copy of the GCC Runtime Library Exception along with this program;
|
|
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
|
// <http://www.gnu.org/licenses/>.
|
|
|
|
/*
|
|
*
|
|
* Copyright (c) 1994
|
|
* Hewlett-Packard Company
|
|
*
|
|
* Permission to use, copy, modify, distribute and sell this software
|
|
* and its documentation for any purpose is hereby granted without fee,
|
|
* provided that the above copyright notice appear in all copies and
|
|
* that both that copyright notice and this permission notice appear
|
|
* in supporting documentation. Hewlett-Packard Company makes no
|
|
* representations about the suitability of this software for any
|
|
* purpose. It is provided "as is" without express or implied warranty.
|
|
*
|
|
*
|
|
* Copyright (c) 1996,1997
|
|
* Silicon Graphics Computer Systems, Inc.
|
|
*
|
|
* Permission to use, copy, modify, distribute and sell this software
|
|
* and its documentation for any purpose is hereby granted without fee,
|
|
* provided that the above copyright notice appear in all copies and
|
|
* that both that copyright notice and this permission notice appear
|
|
* in supporting documentation. Silicon Graphics makes no
|
|
* representations about the suitability of this software for any
|
|
* purpose. It is provided "as is" without express or implied warranty.
|
|
*/
|
|
|
|
/** @file bits/stl_queue.h
|
|
* This is an internal header file, included by other library headers.
|
|
* Do not attempt to use it directly. @headername{queue}
|
|
*/
|
|
|
|
#ifndef _STL_QUEUE_H
|
|
#define _STL_QUEUE_H 1
|
|
|
|
#include <bits/concept_check.h>
|
|
#include <debug/debug.h>
|
|
#if __cplusplus >= 201103L
|
|
# include <bits/uses_allocator.h>
|
|
#endif
|
|
#if __glibcxx_containers_ranges // C++ >= 23
|
|
# include <ranges> // ranges::to
|
|
# include <bits/ranges_algobase.h> // ranges::copy
|
|
#endif
|
|
|
|
namespace std _GLIBCXX_VISIBILITY(default)
|
|
{
|
|
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|
|
|
#if __glibcxx_format_ranges
|
|
template<typename, typename> class formatter;
|
|
#endif
|
|
|
|
/**
|
|
* @brief A standard container giving FIFO behavior.
|
|
*
|
|
* @ingroup sequences
|
|
*
|
|
* @tparam _Tp Type of element.
|
|
* @tparam _Sequence Type of underlying sequence, defaults to deque<_Tp>.
|
|
*
|
|
* Meets many of the requirements of a
|
|
* <a href="tables.html#65">container</a>,
|
|
* but does not define anything to do with iterators. Very few of the
|
|
* other standard container interfaces are defined.
|
|
*
|
|
* This is not a true container, but an @e adaptor. It holds another
|
|
* container, and provides a wrapper interface to that container. The
|
|
* wrapper is what enforces strict first-in-first-out %queue behavior.
|
|
*
|
|
* The second template parameter defines the type of the underlying
|
|
* sequence/container. It defaults to std::deque, but it can be any type
|
|
* that supports @c front, @c back, @c push_back, and @c pop_front,
|
|
* such as std::list or an appropriate user-defined type.
|
|
*
|
|
* Members not found in @a normal containers are @c container_type,
|
|
* which is a typedef for the second Sequence parameter, and @c push and
|
|
* @c pop, which are standard %queue/FIFO operations.
|
|
*/
|
|
template<typename _Tp, typename _Sequence = deque<_Tp> >
|
|
class queue
|
|
{
|
|
#ifdef _GLIBCXX_CONCEPT_CHECKS
|
|
// concept requirements
|
|
typedef typename _Sequence::value_type _Sequence_value_type;
|
|
# if __cplusplus < 201103L
|
|
__glibcxx_class_requires(_Tp, _SGIAssignableConcept)
|
|
# endif
|
|
__glibcxx_class_requires(_Sequence, _FrontInsertionSequenceConcept)
|
|
__glibcxx_class_requires(_Sequence, _BackInsertionSequenceConcept)
|
|
__glibcxx_class_requires2(_Tp, _Sequence_value_type, _SameTypeConcept)
|
|
#endif
|
|
|
|
template<typename _Tp1, typename _Seq1>
|
|
friend bool
|
|
operator==(const queue<_Tp1, _Seq1>&, const queue<_Tp1, _Seq1>&);
|
|
|
|
template<typename _Tp1, typename _Seq1>
|
|
friend bool
|
|
operator<(const queue<_Tp1, _Seq1>&, const queue<_Tp1, _Seq1>&);
|
|
|
|
#if __cpp_lib_three_way_comparison
|
|
template<typename _Tp1, three_way_comparable _Seq1>
|
|
friend compare_three_way_result_t<_Seq1>
|
|
operator<=>(const queue<_Tp1, _Seq1>&, const queue<_Tp1, _Seq1>&);
|
|
#endif
|
|
|
|
#if __cplusplus >= 201103L
|
|
template<typename _Alloc>
|
|
using _Uses = typename
|
|
enable_if<uses_allocator<_Sequence, _Alloc>::value>::type;
|
|
|
|
#if __cplusplus >= 201703L
|
|
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
|
// 2566. Requirements on the first template parameter of container
|
|
// adaptors
|
|
static_assert(is_same<_Tp, typename _Sequence::value_type>::value,
|
|
"value_type must be the same as the underlying container");
|
|
#endif // C++17
|
|
#endif // C++11
|
|
|
|
public:
|
|
typedef typename _Sequence::value_type value_type;
|
|
typedef typename _Sequence::reference reference;
|
|
typedef typename _Sequence::const_reference const_reference;
|
|
typedef typename _Sequence::size_type size_type;
|
|
typedef _Sequence container_type;
|
|
|
|
protected:
|
|
/* Maintainers wondering why this isn't uglified as per style
|
|
* guidelines should note that this name is specified in the standard,
|
|
* C++98 [23.2.3.1].
|
|
* (Why? Presumably for the same reason that it's protected instead
|
|
* of private: to allow derivation. But none of the other
|
|
* containers allow for derivation. Odd.)
|
|
*/
|
|
/// @c c is the underlying container.
|
|
_Sequence c;
|
|
|
|
public:
|
|
/**
|
|
* @brief Default constructor creates no elements.
|
|
*/
|
|
#if __cplusplus < 201103L
|
|
explicit
|
|
queue(const _Sequence& __c = _Sequence())
|
|
: c(__c) { }
|
|
#else
|
|
template<typename _Seq = _Sequence, typename _Requires = typename
|
|
enable_if<is_default_constructible<_Seq>::value>::type>
|
|
queue()
|
|
: c() { }
|
|
|
|
explicit
|
|
queue(const _Sequence& __c)
|
|
: c(__c) { }
|
|
|
|
explicit
|
|
queue(_Sequence&& __c)
|
|
: c(std::move(__c)) { }
|
|
|
|
template<typename _Alloc, typename _Requires = _Uses<_Alloc>>
|
|
explicit
|
|
queue(const _Alloc& __a)
|
|
: c(__a) { }
|
|
|
|
template<typename _Alloc, typename _Requires = _Uses<_Alloc>>
|
|
queue(const _Sequence& __c, const _Alloc& __a)
|
|
: c(__c, __a) { }
|
|
|
|
template<typename _Alloc, typename _Requires = _Uses<_Alloc>>
|
|
queue(_Sequence&& __c, const _Alloc& __a)
|
|
: c(std::move(__c), __a) { }
|
|
|
|
template<typename _Alloc, typename _Requires = _Uses<_Alloc>>
|
|
queue(const queue& __q, const _Alloc& __a)
|
|
: c(__q.c, __a) { }
|
|
|
|
template<typename _Alloc, typename _Requires = _Uses<_Alloc>>
|
|
queue(queue&& __q, const _Alloc& __a)
|
|
: c(std::move(__q.c), __a) { }
|
|
#endif
|
|
|
|
#ifdef __glibcxx_adaptor_iterator_pair_constructor // C++ >= 23 && HOSTED
|
|
template<typename _InputIterator,
|
|
typename = _RequireInputIter<_InputIterator>>
|
|
queue(_InputIterator __first, _InputIterator __last)
|
|
: c(__first, __last) { }
|
|
|
|
template<typename _InputIterator, typename _Alloc,
|
|
typename = _RequireInputIter<_InputIterator>,
|
|
typename = _Uses<_Alloc>>
|
|
queue(_InputIterator __first, _InputIterator __last, const _Alloc& __a)
|
|
: c(__first, __last, __a) { }
|
|
#endif
|
|
|
|
#if __glibcxx_containers_ranges // C++ >= 23
|
|
/**
|
|
* @brief Construct a queue from a range.
|
|
* @since C++23
|
|
*/
|
|
template<__detail::__container_compatible_range<_Tp> _Rg>
|
|
queue(from_range_t, _Rg&& __rg)
|
|
: c(ranges::to<_Sequence>(std::forward<_Rg>(__rg)))
|
|
{ }
|
|
|
|
/**
|
|
* @brief Construct a queue from a range.
|
|
* @since C++23
|
|
*/
|
|
template<__detail::__container_compatible_range<_Tp> _Rg,
|
|
typename _Alloc>
|
|
queue(from_range_t, _Rg&& __rg, const _Alloc& __a)
|
|
: c(ranges::to<_Sequence>(std::forward<_Rg>(__rg), __a))
|
|
{ }
|
|
#endif
|
|
|
|
/**
|
|
* Returns true if the %queue is empty.
|
|
*/
|
|
_GLIBCXX_NODISCARD bool
|
|
empty() const
|
|
{ return c.empty(); }
|
|
|
|
/** Returns the number of elements in the %queue. */
|
|
_GLIBCXX_NODISCARD
|
|
size_type
|
|
size() const
|
|
{ return c.size(); }
|
|
|
|
/**
|
|
* Returns a read/write reference to the data at the first
|
|
* element of the %queue.
|
|
*/
|
|
_GLIBCXX_NODISCARD
|
|
reference
|
|
front()
|
|
{
|
|
__glibcxx_requires_nonempty();
|
|
return c.front();
|
|
}
|
|
|
|
/**
|
|
* Returns a read-only (constant) reference to the data at the first
|
|
* element of the %queue.
|
|
*/
|
|
_GLIBCXX_NODISCARD
|
|
const_reference
|
|
front() const
|
|
{
|
|
__glibcxx_requires_nonempty();
|
|
return c.front();
|
|
}
|
|
|
|
/**
|
|
* Returns a read/write reference to the data at the last
|
|
* element of the %queue.
|
|
*/
|
|
_GLIBCXX_NODISCARD
|
|
reference
|
|
back()
|
|
{
|
|
__glibcxx_requires_nonempty();
|
|
return c.back();
|
|
}
|
|
|
|
/**
|
|
* Returns a read-only (constant) reference to the data at the last
|
|
* element of the %queue.
|
|
*/
|
|
_GLIBCXX_NODISCARD
|
|
const_reference
|
|
back() const
|
|
{
|
|
__glibcxx_requires_nonempty();
|
|
return c.back();
|
|
}
|
|
|
|
/**
|
|
* @brief Add data to the end of the %queue.
|
|
* @param __x Data to be added.
|
|
*
|
|
* This is a typical %queue operation. The function creates an
|
|
* element at the end of the %queue and assigns the given data
|
|
* to it. The time complexity of the operation depends on the
|
|
* underlying sequence.
|
|
*/
|
|
void
|
|
push(const value_type& __x)
|
|
{ c.push_back(__x); }
|
|
|
|
#if __cplusplus >= 201103L
|
|
void
|
|
push(value_type&& __x)
|
|
{ c.push_back(std::move(__x)); }
|
|
|
|
#if __cplusplus > 201402L
|
|
template<typename... _Args>
|
|
decltype(auto)
|
|
emplace(_Args&&... __args)
|
|
{ return c.emplace_back(std::forward<_Args>(__args)...); }
|
|
#else
|
|
template<typename... _Args>
|
|
void
|
|
emplace(_Args&&... __args)
|
|
{ c.emplace_back(std::forward<_Args>(__args)...); }
|
|
#endif
|
|
#endif
|
|
|
|
#if __glibcxx_containers_ranges // C++ >= 23
|
|
template<__detail::__container_compatible_range<_Tp> _Rg>
|
|
void
|
|
push_range(_Rg&& __rg)
|
|
{
|
|
if constexpr (requires { c.append_range(std::forward<_Rg>(__rg)); })
|
|
c.append_range(std::forward<_Rg>(__rg));
|
|
else
|
|
ranges::copy(__rg, std::back_inserter(c));
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* @brief Removes first element.
|
|
*
|
|
* This is a typical %queue operation. It shrinks the %queue by one.
|
|
* The time complexity of the operation depends on the underlying
|
|
* sequence.
|
|
*
|
|
* Note that no data is returned, and if the first element's
|
|
* data is needed, it should be retrieved before pop() is
|
|
* called.
|
|
*/
|
|
void
|
|
pop()
|
|
{
|
|
__glibcxx_requires_nonempty();
|
|
c.pop_front();
|
|
}
|
|
|
|
#if __cplusplus >= 201103L
|
|
void
|
|
swap(queue& __q)
|
|
#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
|
|
noexcept(__is_nothrow_swappable<_Sequence>::value)
|
|
#else
|
|
noexcept(__is_nothrow_swappable<_Tp>::value)
|
|
#endif
|
|
{
|
|
using std::swap;
|
|
swap(c, __q.c);
|
|
}
|
|
#endif // __cplusplus >= 201103L
|
|
|
|
#if __glibcxx_format_ranges
|
|
friend class formatter<queue<_Tp, _Sequence>, char>;
|
|
friend class formatter<queue<_Tp, _Sequence>, wchar_t>;
|
|
#endif
|
|
};
|
|
|
|
#if __cpp_deduction_guides >= 201606
|
|
template<typename _Container,
|
|
typename = _RequireNotAllocator<_Container>>
|
|
queue(_Container) -> queue<typename _Container::value_type, _Container>;
|
|
|
|
template<typename _Container, typename _Allocator,
|
|
typename = _RequireNotAllocator<_Container>>
|
|
queue(_Container, _Allocator)
|
|
-> queue<typename _Container::value_type, _Container>;
|
|
|
|
#ifdef __glibcxx_adaptor_iterator_pair_constructor
|
|
template<typename _InputIterator,
|
|
typename _ValT
|
|
= typename iterator_traits<_InputIterator>::value_type,
|
|
typename = _RequireInputIter<_InputIterator>>
|
|
queue(_InputIterator, _InputIterator) -> queue<_ValT>;
|
|
|
|
template<typename _InputIterator, typename _Allocator,
|
|
typename _ValT
|
|
= typename iterator_traits<_InputIterator>::value_type,
|
|
typename = _RequireInputIter<_InputIterator>,
|
|
typename = _RequireAllocator<_Allocator>>
|
|
queue(_InputIterator, _InputIterator, _Allocator)
|
|
-> queue<_ValT, deque<_ValT, _Allocator>>;
|
|
#endif
|
|
|
|
#if __glibcxx_containers_ranges // C++ >= 23
|
|
template<ranges::input_range _Rg>
|
|
queue(from_range_t, _Rg&&) -> queue<ranges::range_value_t<_Rg>>;
|
|
|
|
template<ranges::input_range _Rg, __allocator_like _Alloc>
|
|
queue(from_range_t, _Rg&&, _Alloc)
|
|
-> queue<ranges::range_value_t<_Rg>,
|
|
deque<ranges::range_value_t<_Rg>, _Alloc>>;
|
|
#endif
|
|
#endif
|
|
|
|
/**
|
|
* @brief Queue equality comparison.
|
|
* @param __x A %queue.
|
|
* @param __y A %queue of the same type as @a __x.
|
|
* @return True iff the size and elements of the queues are equal.
|
|
*
|
|
* This is an equivalence relation. Complexity and semantics depend on the
|
|
* underlying sequence type, but the expected rules are: this relation is
|
|
* linear in the size of the sequences, and queues are considered equivalent
|
|
* if their sequences compare equal.
|
|
*/
|
|
template<typename _Tp, typename _Seq>
|
|
_GLIBCXX_NODISCARD
|
|
inline bool
|
|
operator==(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y)
|
|
{ return __x.c == __y.c; }
|
|
|
|
/**
|
|
* @brief Queue ordering relation.
|
|
* @param __x A %queue.
|
|
* @param __y A %queue of the same type as @a x.
|
|
* @return True iff @a __x is lexicographically less than @a __y.
|
|
*
|
|
* This is an total ordering relation. Complexity and semantics
|
|
* depend on the underlying sequence type, but the expected rules
|
|
* are: this relation is linear in the size of the sequences, the
|
|
* elements must be comparable with @c <, and
|
|
* std::lexicographical_compare() is usually used to make the
|
|
* determination.
|
|
*/
|
|
template<typename _Tp, typename _Seq>
|
|
_GLIBCXX_NODISCARD
|
|
inline bool
|
|
operator<(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y)
|
|
{ return __x.c < __y.c; }
|
|
|
|
/// Based on operator==
|
|
template<typename _Tp, typename _Seq>
|
|
_GLIBCXX_NODISCARD
|
|
inline bool
|
|
operator!=(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y)
|
|
{ return !(__x == __y); }
|
|
|
|
/// Based on operator<
|
|
template<typename _Tp, typename _Seq>
|
|
_GLIBCXX_NODISCARD
|
|
inline bool
|
|
operator>(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y)
|
|
{ return __y < __x; }
|
|
|
|
/// Based on operator<
|
|
template<typename _Tp, typename _Seq>
|
|
_GLIBCXX_NODISCARD
|
|
inline bool
|
|
operator<=(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y)
|
|
{ return !(__y < __x); }
|
|
|
|
/// Based on operator<
|
|
template<typename _Tp, typename _Seq>
|
|
_GLIBCXX_NODISCARD
|
|
inline bool
|
|
operator>=(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y)
|
|
{ return !(__x < __y); }
|
|
|
|
#if __cpp_lib_three_way_comparison
|
|
template<typename _Tp, three_way_comparable _Seq>
|
|
[[nodiscard]]
|
|
inline compare_three_way_result_t<_Seq>
|
|
operator<=>(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y)
|
|
{ return __x.c <=> __y.c; }
|
|
#endif
|
|
|
|
#if __cplusplus >= 201103L
|
|
template<typename _Tp, typename _Seq>
|
|
inline
|
|
#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
|
|
// Constrained free swap overload, see p0185r1
|
|
typename enable_if<__is_swappable<_Seq>::value>::type
|
|
#else
|
|
void
|
|
#endif
|
|
swap(queue<_Tp, _Seq>& __x, queue<_Tp, _Seq>& __y)
|
|
noexcept(noexcept(__x.swap(__y)))
|
|
{ __x.swap(__y); }
|
|
|
|
template<typename _Tp, typename _Seq, typename _Alloc>
|
|
struct uses_allocator<queue<_Tp, _Seq>, _Alloc>
|
|
: public uses_allocator<_Seq, _Alloc>::type { };
|
|
#endif // __cplusplus >= 201103L
|
|
|
|
/**
|
|
* @brief A standard container automatically sorting its contents.
|
|
*
|
|
* @ingroup sequences
|
|
*
|
|
* @tparam _Tp Type of element.
|
|
* @tparam _Sequence Type of underlying sequence, defaults to vector<_Tp>.
|
|
* @tparam _Compare Comparison function object type, defaults to
|
|
* less<_Sequence::value_type>.
|
|
*
|
|
* This is not a true container, but an @e adaptor. It holds
|
|
* another container, and provides a wrapper interface to that
|
|
* container. The wrapper is what enforces priority-based sorting
|
|
* and %queue behavior. Very few of the standard container/sequence
|
|
* interface requirements are met (e.g., iterators).
|
|
*
|
|
* The second template parameter defines the type of the underlying
|
|
* sequence/container. It defaults to std::vector, but it can be
|
|
* any type that supports @c front(), @c push_back, @c pop_back,
|
|
* and random-access iterators, such as std::deque or an
|
|
* appropriate user-defined type.
|
|
*
|
|
* The third template parameter supplies the means of making
|
|
* priority comparisons. It defaults to @c less<value_type> but
|
|
* can be anything defining a strict weak ordering.
|
|
*
|
|
* Members not found in @a normal containers are @c container_type,
|
|
* which is a typedef for the second Sequence parameter, and @c
|
|
* push, @c pop, and @c top, which are standard %queue operations.
|
|
*
|
|
* @note No equality/comparison operators are provided for
|
|
* %priority_queue.
|
|
*
|
|
* @note Sorting of the elements takes place as they are added to,
|
|
* and removed from, the %priority_queue using the
|
|
* %priority_queue's member functions. If you access the elements
|
|
* by other means, and change their data such that the sorting
|
|
* order would be different, the %priority_queue will not re-sort
|
|
* the elements for you. (How could it know to do so?)
|
|
*/
|
|
template<typename _Tp, typename _Sequence = vector<_Tp>,
|
|
typename _Compare = less<typename _Sequence::value_type> >
|
|
class priority_queue
|
|
{
|
|
#ifdef _GLIBCXX_CONCEPT_CHECKS
|
|
// concept requirements
|
|
typedef typename _Sequence::value_type _Sequence_value_type;
|
|
# if __cplusplus < 201103L
|
|
__glibcxx_class_requires(_Tp, _SGIAssignableConcept)
|
|
# endif
|
|
__glibcxx_class_requires(_Sequence, _SequenceConcept)
|
|
__glibcxx_class_requires(_Sequence, _RandomAccessContainerConcept)
|
|
__glibcxx_class_requires2(_Tp, _Sequence_value_type, _SameTypeConcept)
|
|
__glibcxx_class_requires4(_Compare, bool, _Tp, _Tp,
|
|
_BinaryFunctionConcept)
|
|
#endif
|
|
|
|
#if __cplusplus >= 201103L
|
|
template<typename _Alloc>
|
|
using _Uses = typename
|
|
enable_if<uses_allocator<_Sequence, _Alloc>::value>::type;
|
|
|
|
#if __cplusplus >= 201703L
|
|
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
|
// 2566. Requirements on the first template parameter of container
|
|
// adaptors
|
|
static_assert(is_same<_Tp, typename _Sequence::value_type>::value,
|
|
"value_type must be the same as the underlying container");
|
|
#endif // C++17
|
|
#endif // C++11
|
|
|
|
public:
|
|
typedef typename _Sequence::value_type value_type;
|
|
typedef typename _Sequence::reference reference;
|
|
typedef typename _Sequence::const_reference const_reference;
|
|
typedef typename _Sequence::size_type size_type;
|
|
typedef _Sequence container_type;
|
|
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
|
// DR 2684. priority_queue lacking comparator typedef
|
|
typedef _Compare value_compare;
|
|
|
|
protected:
|
|
// See queue::c for notes on these names.
|
|
_Sequence c;
|
|
_Compare comp;
|
|
|
|
public:
|
|
/**
|
|
* @brief Default constructor creates no elements.
|
|
*/
|
|
#if __cplusplus < 201103L
|
|
explicit
|
|
priority_queue(const _Compare& __x = _Compare(),
|
|
const _Sequence& __s = _Sequence())
|
|
: c(__s), comp(__x)
|
|
{ std::make_heap(c.begin(), c.end(), comp); }
|
|
#else
|
|
template<typename _Seq = _Sequence, typename _Requires = typename
|
|
enable_if<__and_<is_default_constructible<_Compare>,
|
|
is_default_constructible<_Seq>>::value>::type>
|
|
priority_queue()
|
|
: c(), comp() { }
|
|
|
|
explicit
|
|
priority_queue(const _Compare& __x, const _Sequence& __s)
|
|
: c(__s), comp(__x)
|
|
{ std::make_heap(c.begin(), c.end(), comp); }
|
|
|
|
explicit
|
|
priority_queue(const _Compare& __x, _Sequence&& __s = _Sequence())
|
|
: c(std::move(__s)), comp(__x)
|
|
{ std::make_heap(c.begin(), c.end(), comp); }
|
|
|
|
priority_queue(const priority_queue&) = default;
|
|
priority_queue& operator=(const priority_queue&) = default;
|
|
|
|
priority_queue(priority_queue&& __q)
|
|
noexcept(__and_<is_nothrow_move_constructible<_Sequence>,
|
|
is_nothrow_move_constructible<_Compare>>::value)
|
|
: c(std::move(__q.c)), comp(std::move(__q.comp))
|
|
{ __q.c.clear(); }
|
|
|
|
priority_queue&
|
|
operator=(priority_queue&& __q)
|
|
noexcept(__and_<is_nothrow_move_assignable<_Sequence>,
|
|
is_nothrow_move_assignable<_Compare>>::value)
|
|
{
|
|
c = std::move(__q.c);
|
|
__q.c.clear();
|
|
comp = std::move(__q.comp);
|
|
return *this;
|
|
}
|
|
|
|
template<typename _Alloc, typename _Requires = _Uses<_Alloc>>
|
|
explicit
|
|
priority_queue(const _Alloc& __a)
|
|
: c(__a), comp() { }
|
|
|
|
template<typename _Alloc, typename _Requires = _Uses<_Alloc>>
|
|
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>>
|
|
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>>
|
|
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>>
|
|
priority_queue(const priority_queue& __q, const _Alloc& __a)
|
|
: c(__q.c, __a), comp(__q.comp) { }
|
|
|
|
template<typename _Alloc, typename _Requires = _Uses<_Alloc>>
|
|
priority_queue(priority_queue&& __q, const _Alloc& __a)
|
|
: c(std::move(__q.c), __a), comp(std::move(__q.comp))
|
|
{ __q.c.clear(); }
|
|
#endif
|
|
|
|
/**
|
|
* @brief Builds a %queue from a range.
|
|
* @param __first An input iterator.
|
|
* @param __last An input iterator.
|
|
* @param __x A comparison functor describing a strict weak ordering.
|
|
* @param __s An initial sequence with which to start.
|
|
*
|
|
* Begins by copying @a __s, inserting a copy of the elements
|
|
* from @a [first,last) into the copy of @a __s, then ordering
|
|
* the copy according to @a __x.
|
|
*
|
|
* For more information on function objects, see the
|
|
* documentation on @link functors functor base classes@endlink.
|
|
*/
|
|
#if __cplusplus < 201103L
|
|
template<typename _InputIterator>
|
|
priority_queue(_InputIterator __first, _InputIterator __last,
|
|
const _Compare& __x = _Compare(),
|
|
const _Sequence& __s = _Sequence())
|
|
: c(__s), comp(__x)
|
|
{
|
|
__glibcxx_requires_valid_range(__first, __last);
|
|
c.insert(c.end(), __first, __last);
|
|
std::make_heap(c.begin(), c.end(), comp);
|
|
}
|
|
#else
|
|
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
|
// 3529. priority_queue(first, last) should construct c with (first, last)
|
|
template<typename _InputIterator,
|
|
typename = std::_RequireInputIter<_InputIterator>>
|
|
priority_queue(_InputIterator __first, _InputIterator __last,
|
|
const _Compare& __x = _Compare())
|
|
: c(__first, __last), comp(__x)
|
|
{ std::make_heap(c.begin(), c.end(), comp); }
|
|
|
|
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
|
// 3522. Missing requirement on InputIterator template parameter
|
|
template<typename _InputIterator,
|
|
typename = std::_RequireInputIter<_InputIterator>>
|
|
priority_queue(_InputIterator __first, _InputIterator __last,
|
|
const _Compare& __x, const _Sequence& __s)
|
|
: c(__s), comp(__x)
|
|
{
|
|
__glibcxx_requires_valid_range(__first, __last);
|
|
c.insert(c.end(), __first, __last);
|
|
std::make_heap(c.begin(), c.end(), comp);
|
|
}
|
|
|
|
template<typename _InputIterator,
|
|
typename = std::_RequireInputIter<_InputIterator>>
|
|
priority_queue(_InputIterator __first, _InputIterator __last,
|
|
const _Compare& __x, _Sequence&& __s)
|
|
: c(std::move(__s)), comp(__x)
|
|
{
|
|
__glibcxx_requires_valid_range(__first, __last);
|
|
c.insert(c.end(), __first, __last);
|
|
std::make_heap(c.begin(), c.end(), comp);
|
|
}
|
|
|
|
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
|
// 3506. Missing allocator-extended constructors for priority_queue
|
|
template<typename _InputIterator, typename _Alloc,
|
|
typename = std::_RequireInputIter<_InputIterator>,
|
|
typename _Requires = _Uses<_Alloc>>
|
|
priority_queue(_InputIterator __first, _InputIterator __last,
|
|
const _Alloc& __alloc)
|
|
: c(__first, __last, __alloc), comp()
|
|
{ std::make_heap(c.begin(), c.end(), comp); }
|
|
|
|
template<typename _InputIterator, typename _Alloc,
|
|
typename = std::_RequireInputIter<_InputIterator>,
|
|
typename _Requires = _Uses<_Alloc>>
|
|
priority_queue(_InputIterator __first, _InputIterator __last,
|
|
const _Compare& __x, const _Alloc& __alloc)
|
|
: c(__first, __last, __alloc), comp(__x)
|
|
{ std::make_heap(c.begin(), c.end(), comp); }
|
|
|
|
template<typename _InputIterator, typename _Alloc,
|
|
typename = std::_RequireInputIter<_InputIterator>,
|
|
typename _Requires = _Uses<_Alloc>>
|
|
priority_queue(_InputIterator __first, _InputIterator __last,
|
|
const _Compare& __x, const _Sequence& __s,
|
|
const _Alloc& __alloc)
|
|
: c(__s, __alloc), comp(__x)
|
|
{
|
|
__glibcxx_requires_valid_range(__first, __last);
|
|
c.insert(c.end(), __first, __last);
|
|
std::make_heap(c.begin(), c.end(), comp);
|
|
}
|
|
|
|
template<typename _InputIterator, typename _Alloc,
|
|
typename _Requires = _Uses<_Alloc>>
|
|
priority_queue(_InputIterator __first, _InputIterator __last,
|
|
const _Compare& __x, _Sequence&& __s,
|
|
const _Alloc& __alloc)
|
|
: c(std::move(__s), __alloc), comp(__x)
|
|
{
|
|
__glibcxx_requires_valid_range(__first, __last);
|
|
c.insert(c.end(), __first, __last);
|
|
std::make_heap(c.begin(), c.end(), comp);
|
|
}
|
|
#endif
|
|
|
|
#if __glibcxx_containers_ranges // C++ >= 23
|
|
/**
|
|
* @brief Construct a priority_queue from a range.
|
|
* @since C++23
|
|
*
|
|
* @{
|
|
*/
|
|
template<__detail::__container_compatible_range<_Tp> _Rg>
|
|
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>
|
|
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>
|
|
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); }
|
|
/// @}
|
|
#endif
|
|
|
|
/**
|
|
* Returns true if the %queue is empty.
|
|
*/
|
|
_GLIBCXX_NODISCARD bool
|
|
empty() const
|
|
{ return c.empty(); }
|
|
|
|
/** Returns the number of elements in the %queue. */
|
|
_GLIBCXX_NODISCARD
|
|
size_type
|
|
size() const
|
|
{ return c.size(); }
|
|
|
|
/**
|
|
* Returns a read-only (constant) reference to the data at the first
|
|
* element of the %queue.
|
|
*/
|
|
_GLIBCXX_NODISCARD
|
|
const_reference
|
|
top() const
|
|
{
|
|
__glibcxx_requires_nonempty();
|
|
return c.front();
|
|
}
|
|
|
|
/**
|
|
* @brief Add data to the %queue.
|
|
* @param __x Data to be added.
|
|
*
|
|
* This is a typical %queue operation.
|
|
* The time complexity of the operation depends on the underlying
|
|
* sequence.
|
|
*/
|
|
void
|
|
push(const value_type& __x)
|
|
{
|
|
c.push_back(__x);
|
|
std::push_heap(c.begin(), c.end(), comp);
|
|
}
|
|
|
|
#if __cplusplus >= 201103L
|
|
void
|
|
push(value_type&& __x)
|
|
{
|
|
c.push_back(std::move(__x));
|
|
std::push_heap(c.begin(), c.end(), comp);
|
|
}
|
|
|
|
template<typename... _Args>
|
|
void
|
|
emplace(_Args&&... __args)
|
|
{
|
|
c.emplace_back(std::forward<_Args>(__args)...);
|
|
std::push_heap(c.begin(), c.end(), comp);
|
|
}
|
|
#endif
|
|
|
|
#if __glibcxx_containers_ranges // C++ >= 23
|
|
template<__detail::__container_compatible_range<_Tp> _Rg>
|
|
void
|
|
push_range(_Rg&& __rg)
|
|
{
|
|
if constexpr (requires { c.append_range(std::forward<_Rg>(__rg)); })
|
|
c.append_range(std::forward<_Rg>(__rg));
|
|
else
|
|
ranges::copy(__rg, std::back_inserter(c));
|
|
std::make_heap(c.begin(), c.end(), comp);
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* @brief Removes first element.
|
|
*
|
|
* This is a typical %queue operation. It shrinks the %queue
|
|
* by one. The time complexity of the operation depends on the
|
|
* underlying sequence.
|
|
*
|
|
* Note that no data is returned, and if the first element's
|
|
* data is needed, it should be retrieved before pop() is
|
|
* called.
|
|
*/
|
|
void
|
|
pop()
|
|
{
|
|
__glibcxx_requires_nonempty();
|
|
std::pop_heap(c.begin(), c.end(), comp);
|
|
c.pop_back();
|
|
}
|
|
|
|
#if __cplusplus >= 201103L
|
|
void
|
|
swap(priority_queue& __pq)
|
|
noexcept(__and_<
|
|
#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
|
|
__is_nothrow_swappable<_Sequence>,
|
|
#else
|
|
__is_nothrow_swappable<_Tp>,
|
|
#endif
|
|
__is_nothrow_swappable<_Compare>
|
|
>::value)
|
|
{
|
|
using std::swap;
|
|
swap(c, __pq.c);
|
|
swap(comp, __pq.comp);
|
|
}
|
|
#endif // __cplusplus >= 201103L
|
|
|
|
#if __glibcxx_format_ranges
|
|
friend class formatter<priority_queue<_Tp, _Sequence, _Compare>, char>;
|
|
friend class formatter<priority_queue<_Tp, _Sequence, _Compare>, wchar_t>;
|
|
#endif
|
|
};
|
|
|
|
#if __cpp_deduction_guides >= 201606
|
|
template<typename _Compare, typename _Container,
|
|
typename = _RequireNotAllocator<_Compare>,
|
|
typename = _RequireNotAllocator<_Container>>
|
|
priority_queue(_Compare, _Container)
|
|
-> priority_queue<typename _Container::value_type, _Container, _Compare>;
|
|
|
|
template<typename _InputIterator, typename _ValT
|
|
= typename iterator_traits<_InputIterator>::value_type,
|
|
typename _Compare = less<_ValT>,
|
|
typename _Container = vector<_ValT>,
|
|
typename = _RequireInputIter<_InputIterator>,
|
|
typename = _RequireNotAllocator<_Compare>,
|
|
typename = _RequireNotAllocator<_Container>>
|
|
priority_queue(_InputIterator, _InputIterator, _Compare = _Compare(),
|
|
_Container = _Container())
|
|
-> priority_queue<_ValT, _Container, _Compare>;
|
|
|
|
template<typename _Compare, typename _Container, typename _Allocator,
|
|
typename = _RequireNotAllocator<_Compare>,
|
|
typename = _RequireNotAllocator<_Container>>
|
|
priority_queue(_Compare, _Container, _Allocator)
|
|
-> priority_queue<typename _Container::value_type, _Container, _Compare>;
|
|
|
|
#if __glibcxx_containers_ranges // C++ >= 23
|
|
template<ranges::input_range _Rg,
|
|
__not_allocator_like _Compare = less<ranges::range_value_t<_Rg>>,
|
|
__allocator_like _Alloc = std::allocator<ranges::range_value_t<_Rg>>>
|
|
priority_queue(from_range_t, _Rg&&, _Compare = _Compare(),
|
|
_Alloc = _Alloc())
|
|
-> priority_queue<ranges::range_value_t<_Rg>,
|
|
vector<ranges::range_value_t<_Rg>, _Alloc>,
|
|
_Compare>;
|
|
|
|
template<ranges::input_range _Rg, __allocator_like _Alloc>
|
|
priority_queue(from_range_t, _Rg&&, _Alloc)
|
|
-> priority_queue<ranges::range_value_t<_Rg>,
|
|
vector<ranges::range_value_t<_Rg>, _Alloc>>;
|
|
#endif
|
|
#endif
|
|
|
|
// No equality/comparison operators are provided for priority_queue.
|
|
|
|
#if __cplusplus >= 201103L
|
|
template<typename _Tp, typename _Sequence, typename _Compare>
|
|
inline
|
|
#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
|
|
// Constrained free swap overload, see p0185r1
|
|
typename enable_if<__and_<__is_swappable<_Sequence>,
|
|
__is_swappable<_Compare>>::value>::type
|
|
#else
|
|
void
|
|
#endif
|
|
swap(priority_queue<_Tp, _Sequence, _Compare>& __x,
|
|
priority_queue<_Tp, _Sequence, _Compare>& __y)
|
|
noexcept(noexcept(__x.swap(__y)))
|
|
{ __x.swap(__y); }
|
|
|
|
template<typename _Tp, typename _Sequence, typename _Compare,
|
|
typename _Alloc>
|
|
struct uses_allocator<priority_queue<_Tp, _Sequence, _Compare>, _Alloc>
|
|
: public uses_allocator<_Sequence, _Alloc>::type { };
|
|
#endif // __cplusplus >= 201103L
|
|
|
|
_GLIBCXX_END_NAMESPACE_VERSION
|
|
} // namespace
|
|
|
|
#endif /* _STL_QUEUE_H */
|