mirror of
https://github.com/gcc-mirror/gcc.git
synced 2026-05-06 23:25:24 +02: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>
489 lines
15 KiB
C++
489 lines
15 KiB
C++
// Stack 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_stack.h
|
|
* This is an internal header file, included by other library headers.
|
|
* Do not attempt to use it directly. @headername{stack}
|
|
*/
|
|
|
|
#ifndef _STL_STACK_H
|
|
#define _STL_STACK_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 FILO 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-last-out %stack 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 back, @c push_back, and @c pop_back,
|
|
* such as std::list, std::vector, 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, @c pop, and @c top, which are standard %stack/FILO
|
|
* operations.
|
|
*/
|
|
template<typename _Tp, typename _Sequence = deque<_Tp> >
|
|
class stack
|
|
{
|
|
#ifdef _GLIBCXX_CONCEPT_CHECKS
|
|
// concept requirements
|
|
typedef typename _Sequence::value_type _Sequence_value_type;
|
|
# if __cplusplus < 201103L
|
|
__glibcxx_class_requires(_Tp, _SGIAssignableConcept)
|
|
__glibcxx_class_requires(_Sequence, _BackInsertionSequenceConcept)
|
|
# endif
|
|
__glibcxx_class_requires2(_Tp, _Sequence_value_type, _SameTypeConcept)
|
|
#endif
|
|
|
|
template<typename _Tp1, typename _Seq1>
|
|
friend bool
|
|
operator==(const stack<_Tp1, _Seq1>&, const stack<_Tp1, _Seq1>&);
|
|
|
|
template<typename _Tp1, typename _Seq1>
|
|
friend bool
|
|
operator<(const stack<_Tp1, _Seq1>&, const stack<_Tp1, _Seq1>&);
|
|
|
|
#if __cpp_lib_three_way_comparison
|
|
template<typename _Tp1, three_way_comparable _Seq1>
|
|
friend compare_three_way_result_t<_Seq1>
|
|
operator<=>(const stack<_Tp1, _Seq1>&, const stack<_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:
|
|
// See queue::c for notes on this name.
|
|
_Sequence c;
|
|
|
|
public:
|
|
// XXX removed old def ctor, added def arg to this one to match 14882
|
|
/**
|
|
* @brief Default constructor creates no elements.
|
|
*/
|
|
#if __cplusplus < 201103L
|
|
explicit
|
|
stack(const _Sequence& __c = _Sequence())
|
|
: c(__c) { }
|
|
#else
|
|
template<typename _Seq = _Sequence, typename _Requires = typename
|
|
enable_if<is_default_constructible<_Seq>::value>::type>
|
|
stack()
|
|
: c() { }
|
|
|
|
explicit
|
|
stack(const _Sequence& __c)
|
|
: c(__c) { }
|
|
|
|
explicit
|
|
stack(_Sequence&& __c)
|
|
: c(std::move(__c)) { }
|
|
|
|
#ifdef __glibcxx_adaptor_iterator_pair_constructor // C++ >= 23 && HOSTED
|
|
template<typename _InputIterator,
|
|
typename = _RequireInputIter<_InputIterator>>
|
|
stack(_InputIterator __first, _InputIterator __last)
|
|
: c(__first, __last) { }
|
|
#endif
|
|
|
|
#if __glibcxx_containers_ranges // C++ >= 23
|
|
/**
|
|
* @brief Construct a stack from a range.
|
|
* @since C++23
|
|
*/
|
|
template<__detail::__container_compatible_range<_Tp> _Rg>
|
|
stack(from_range_t, _Rg&& __rg)
|
|
: c(ranges::to<_Sequence>(std::forward<_Rg>(__rg)))
|
|
{ }
|
|
|
|
/**
|
|
* @brief Construct a stack from a range.
|
|
* @since C++23
|
|
*/
|
|
template<__detail::__container_compatible_range<_Tp> _Rg,
|
|
typename _Alloc>
|
|
stack(from_range_t, _Rg&& __rg, const _Alloc& __a)
|
|
: c(ranges::to<_Sequence>(std::forward<_Rg>(__rg), __a))
|
|
{ }
|
|
#endif
|
|
|
|
template<typename _Alloc, typename _Requires = _Uses<_Alloc>>
|
|
explicit
|
|
stack(const _Alloc& __a)
|
|
: c(__a) { }
|
|
|
|
template<typename _Alloc, typename _Requires = _Uses<_Alloc>>
|
|
stack(const _Sequence& __c, const _Alloc& __a)
|
|
: c(__c, __a) { }
|
|
|
|
template<typename _Alloc, typename _Requires = _Uses<_Alloc>>
|
|
stack(_Sequence&& __c, const _Alloc& __a)
|
|
: c(std::move(__c), __a) { }
|
|
|
|
template<typename _Alloc, typename _Requires = _Uses<_Alloc>>
|
|
stack(const stack& __q, const _Alloc& __a)
|
|
: c(__q.c, __a) { }
|
|
|
|
template<typename _Alloc, typename _Requires = _Uses<_Alloc>>
|
|
stack(stack&& __q, const _Alloc& __a)
|
|
: c(std::move(__q.c), __a) { }
|
|
|
|
#if __cplusplus > 202002L
|
|
template<typename _InputIterator, typename _Alloc,
|
|
typename = _RequireInputIter<_InputIterator>,
|
|
typename = _Uses<_Alloc>>
|
|
stack(_InputIterator __first, _InputIterator __last, const _Alloc& __a)
|
|
: c(__first, __last, __a) { }
|
|
#endif
|
|
#endif
|
|
|
|
/**
|
|
* Returns true if the %stack is empty.
|
|
*/
|
|
_GLIBCXX_NODISCARD bool
|
|
empty() const
|
|
{ return c.empty(); }
|
|
|
|
/** Returns the number of elements in the %stack. */
|
|
_GLIBCXX_NODISCARD
|
|
size_type
|
|
size() const
|
|
{ return c.size(); }
|
|
|
|
/**
|
|
* Returns a read/write reference to the data at the first
|
|
* element of the %stack.
|
|
*/
|
|
_GLIBCXX_NODISCARD
|
|
reference
|
|
top()
|
|
{
|
|
__glibcxx_requires_nonempty();
|
|
return c.back();
|
|
}
|
|
|
|
/**
|
|
* Returns a read-only (constant) reference to the data at the first
|
|
* element of the %stack.
|
|
*/
|
|
_GLIBCXX_NODISCARD
|
|
const_reference
|
|
top() const
|
|
{
|
|
__glibcxx_requires_nonempty();
|
|
return c.back();
|
|
}
|
|
|
|
/**
|
|
* @brief Add data to the top of the %stack.
|
|
* @param __x Data to be added.
|
|
*
|
|
* This is a typical %stack operation. The function creates an
|
|
* element at the top of the %stack 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 %stack operation. It shrinks the %stack
|
|
* 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_back();
|
|
}
|
|
|
|
#if __cplusplus >= 201103L
|
|
void
|
|
swap(stack& __s)
|
|
#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, __s.c);
|
|
}
|
|
#endif // __cplusplus >= 201103L
|
|
|
|
#if __glibcxx_format_ranges
|
|
friend class formatter<stack<_Tp, _Sequence>, char>;
|
|
friend class formatter<stack<_Tp, _Sequence>, wchar_t>;
|
|
#endif
|
|
};
|
|
|
|
#if __cpp_deduction_guides >= 201606
|
|
template<typename _Container,
|
|
typename = _RequireNotAllocator<_Container>>
|
|
stack(_Container) -> stack<typename _Container::value_type, _Container>;
|
|
|
|
template<typename _Container, typename _Allocator,
|
|
typename = _RequireNotAllocator<_Container>>
|
|
stack(_Container, _Allocator)
|
|
-> stack<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>>
|
|
stack(_InputIterator, _InputIterator) -> stack<_ValT>;
|
|
|
|
template<typename _InputIterator, typename _Allocator,
|
|
typename _ValT
|
|
= typename iterator_traits<_InputIterator>::value_type,
|
|
typename = _RequireInputIter<_InputIterator>,
|
|
typename = _RequireAllocator<_Allocator>>
|
|
stack(_InputIterator, _InputIterator, _Allocator)
|
|
-> stack<_ValT, deque<_ValT, _Allocator>>;
|
|
#endif
|
|
|
|
#if __glibcxx_containers_ranges // C++ >= 23
|
|
template<ranges::input_range _Rg>
|
|
stack(from_range_t, _Rg&&) -> stack<ranges::range_value_t<_Rg>>;
|
|
|
|
template<ranges::input_range _Rg, __allocator_like _Alloc>
|
|
stack(from_range_t, _Rg&&, _Alloc)
|
|
-> stack<ranges::range_value_t<_Rg>,
|
|
deque<ranges::range_value_t<_Rg>, _Alloc>>;
|
|
#endif
|
|
#endif
|
|
|
|
/**
|
|
* @brief Stack equality comparison.
|
|
* @param __x A %stack.
|
|
* @param __y A %stack of the same type as @a __x.
|
|
* @return True iff the size and elements of the stacks 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
|
|
* stacks are considered equivalent if their sequences compare
|
|
* equal.
|
|
*/
|
|
template<typename _Tp, typename _Seq>
|
|
_GLIBCXX_NODISCARD
|
|
inline bool
|
|
operator==(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y)
|
|
{ return __x.c == __y.c; }
|
|
|
|
/**
|
|
* @brief Stack ordering relation.
|
|
* @param __x A %stack.
|
|
* @param __y A %stack 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 stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y)
|
|
{ return __x.c < __y.c; }
|
|
|
|
/// Based on operator==
|
|
template<typename _Tp, typename _Seq>
|
|
_GLIBCXX_NODISCARD
|
|
inline bool
|
|
operator!=(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y)
|
|
{ return !(__x == __y); }
|
|
|
|
/// Based on operator<
|
|
template<typename _Tp, typename _Seq>
|
|
_GLIBCXX_NODISCARD
|
|
inline bool
|
|
operator>(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y)
|
|
{ return __y < __x; }
|
|
|
|
/// Based on operator<
|
|
template<typename _Tp, typename _Seq>
|
|
_GLIBCXX_NODISCARD
|
|
inline bool
|
|
operator<=(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y)
|
|
{ return !(__y < __x); }
|
|
|
|
/// Based on operator<
|
|
template<typename _Tp, typename _Seq>
|
|
_GLIBCXX_NODISCARD
|
|
inline bool
|
|
operator>=(const stack<_Tp, _Seq>& __x, const stack<_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 stack<_Tp, _Seq>& __x, const stack<_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(stack<_Tp, _Seq>& __x, stack<_Tp, _Seq>& __y)
|
|
noexcept(noexcept(__x.swap(__y)))
|
|
{ __x.swap(__y); }
|
|
|
|
template<typename _Tp, typename _Seq, typename _Alloc>
|
|
struct uses_allocator<stack<_Tp, _Seq>, _Alloc>
|
|
: public uses_allocator<_Seq, _Alloc>::type { };
|
|
#endif // __cplusplus >= 201103L
|
|
|
|
_GLIBCXX_END_NAMESPACE_VERSION
|
|
} // namespace
|
|
|
|
#endif /* _STL_STACK_H */
|