[PATCH] libstdc++: Make std::stack conxtexpr.

Tomasz Kaminski tkaminsk@redhat.com
Wed Aug 19 10:56:11 GMT 2026


On Wed, Aug 19, 2026 at 12:37 PM Jonathan Wakely <jwakely@redhat.com> wrote:

> Typo of "constexpr" in the subject line
>
>
> On Mon, 10 Aug 2026 at 10:00, Tomasz Kamiński wrote:
> >
> > This patch make stack and it's formatter constexpr, implementing
> > corresponding part of P3372, "constexpr containers and adaptors",
> > and final parts of P3391R2, "constexpr format".
> >
> > libstdc++-v3/ChangeLog:
> >
> >         * include/bits/stl_stack.h (std::stack): Declare members as
> >         _GLIBCXX26_CONSTEXPR.
> >         (std::operator==, std::operator!=, std::operator<,
> std::operator>)
> >         (std::operator<=, std::operator>=, std::operator<=>, std::swap):
> >         Declare as _GLIBCXX26_CONSTEXPR.
> >         * include/bits/version.def (constexpr_stack): Define.
> >         * include/bits/version.h: Regenerate.
> >         * include/std/stack (__cpp_lib_constexpr_stack): Define.
> >         * (formatter<stack<....>, _CharT>::format)
> >         [__glibcxx_constexpr_format]: Declare as constexpr.
> >         * testsuite/23_containers/headers/stack/synopsis.cc:
> >         Update declarations.
> >         * testsuite/std/format/ranges/adaptors.cc: Expand test to stack.
> >         * testsuite/23_containers/stack/constexpr.cc: New test derived
> >         from 23_containers/queue/constexpr.cc.
> > ---
> > Updated also stack, so I will not forgget about updating the formatter
> > later (and I could reuse the test).
> >
> > Tested on x86_64-linux. *format/ranges/adaptors.cc* and *stack* also
> > tested in all standard modes, debug and -m32. OK for trunk?
> >
> >  libstdc++-v3/include/bits/stl_stack.h         |  58 +++--
> >  libstdc++-v3/include/bits/version.def         |   9 +
> >  libstdc++-v3/include/bits/version.h           |  10 +
> >  libstdc++-v3/include/std/stack                |   4 +
> >  .../23_containers/headers/stack/synopsis.cc   |  30 ++-
> >  .../23_containers/stack/constexpr.cc          | 241 ++++++++++++++++++
> >  .../testsuite/std/format/ranges/adaptors.cc   |   1 +
> >  7 files changed, 317 insertions(+), 36 deletions(-)
> >  create mode 100644
> libstdc++-v3/testsuite/23_containers/stack/constexpr.cc
> >
> > diff --git a/libstdc++-v3/include/bits/stl_stack.h
> b/libstdc++-v3/include/bits/stl_stack.h
> > index 94b05776049..fd29579e21a 100644
> > --- a/libstdc++-v3/include/bits/stl_stack.h
> > +++ b/libstdc++-v3/include/bits/stl_stack.h
> > @@ -117,16 +117,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >  #endif
> >
> >        template<typename _Tp1, typename _Seq1>
> > -       friend bool
> > +       friend _GLIBCXX26_CONSTEXPR bool
> >         operator==(const stack<_Tp1, _Seq1>&, const stack<_Tp1, _Seq1>&);
> >
> >        template<typename _Tp1, typename _Seq1>
> > -       friend bool
> > +       friend _GLIBCXX26_CONSTEXPR 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>
> > +       friend _GLIBCXX26_CONSTEXPR compare_three_way_result_t<_Seq1>
> >         operator<=>(const stack<_Tp1, _Seq1>&, const stack<_Tp1,
> _Seq1>&);
> >  #endif
> >
> > @@ -167,20 +167,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >  #else
> >        template<typename _Seq = _Sequence, typename _Requires = typename
> >                enable_if<is_default_constructible<_Seq>::value>::type>
> > +        _GLIBCXX26_CONSTEXPR
> >         stack()
> >         : c() { }
> >
> > -      explicit
> > +      explicit _GLIBCXX26_CONSTEXPR
> >        stack(const _Sequence& __c)
> >        : c(__c) { }
> >
> > -      explicit
> > +      explicit _GLIBCXX26_CONSTEXPR
> >        stack(_Sequence&& __c)
> >        : c(std::move(__c)) { }
> >
> >  #ifdef __glibcxx_adaptor_iterator_pair_constructor // C++ >= 23 &&
> HOSTED
> >        template<typename _InputIterator,
> >                typename = _RequireInputIter<_InputIterator>>
> > +        _GLIBCXX26_CONSTEXPR
> >         stack(_InputIterator __first, _InputIterator __last)
> >         : c(__first, __last) { }
> >  #endif
> > @@ -191,6 +193,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >         * @since C++23
> >         */
> >        template<__detail::__container_compatible_range<_Tp> _Rg>
> > +        _GLIBCXX26_CONSTEXPR
> >         stack(from_range_t, _Rg&& __rg)
> >         : c(ranges::to<_Sequence>(std::forward<_Rg>(__rg)))
> >         { }
> > @@ -201,29 +204,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >         */
> >        template<__detail::__container_compatible_range<_Tp> _Rg,
> >                typename _Alloc>
> > +        _GLIBCXX26_CONSTEXPR
> >         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
> > +       explicit _GLIBCXX26_CONSTEXPR
> >         stack(const _Alloc& __a)
> >         : c(__a) { }
> >
> >        template<typename _Alloc, typename _Requires = _Uses<_Alloc>>
> > +        _GLIBCXX26_CONSTEXPR
> >         stack(const _Sequence& __c, const _Alloc& __a)
> >         : c(__c, __a) { }
> >
> >        template<typename _Alloc, typename _Requires = _Uses<_Alloc>>
> > +        _GLIBCXX26_CONSTEXPR
> >         stack(_Sequence&& __c, const _Alloc& __a)
> >         : c(std::move(__c), __a) { }
> >
> >        template<typename _Alloc, typename _Requires = _Uses<_Alloc>>
> > +        _GLIBCXX26_CONSTEXPR
> >         stack(const stack& __q, const _Alloc& __a)
> >         : c(__q.c, __a) { }
> >
> >        template<typename _Alloc, typename _Requires = _Uses<_Alloc>>
> > +        _GLIBCXX26_CONSTEXPR
> >         stack(stack&& __q, const _Alloc& __a)
> >         : c(std::move(__q.c), __a) { }
> >
> > @@ -231,6 +239,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >        template<typename _InputIterator, typename _Alloc,
> >                typename = _RequireInputIter<_InputIterator>,
> >                typename = _Uses<_Alloc>>
> > +        _GLIBCXX26_CONSTEXPR
> >         stack(_InputIterator __first, _InputIterator __last, const
> _Alloc& __a)
> >         : c(__first, __last, __a) { }
> >  #endif
> > @@ -239,13 +248,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >        /**
> >         *  Returns true if the %stack is empty.
> >         */
> > -      _GLIBCXX_NODISCARD bool
> > +      _GLIBCXX_NODISCARD
> > +      _GLIBCXX26_CONSTEXPR bool
>
> Elsewhere we have the ugly NODISCARD and CONSTEXPR macros on the same
> line, and the return type on a separate line. See for example
> std::string and std::vector. I think it's more readable that way.
>
But on the other side, we usually have constexpr (the non-macro version),
at the same line, and I am looking for them there. Also, I see a NODISCARD
as fluff, but constexpr is sometimes meaningful, so prefer having
constexpr and constexpr-from-cxx26 on the same line.
That's what I also did for deque.

>
> OK for trunk with the typo fixed and those whitepace changes.
>
Let me know, if I should still change the CONSTEXPR placement, to keep
consistency with the rest of the containers. That's actually convincing
argument,

>
> >        empty() const
> >        { return c.empty(); }
> >
> >        /**  Returns the number of elements in the %stack.  */
> >        _GLIBCXX_NODISCARD
> > -      size_type
> > +      _GLIBCXX26_CONSTEXPR size_type
> >        size() const
> >        { return c.size(); }
> >
> > @@ -254,7 +264,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >         *  element of the %stack.
> >         */
> >        _GLIBCXX_NODISCARD
> > -      reference
> > +      _GLIBCXX26_CONSTEXPR reference
> >        top()
> >        {
> >         __glibcxx_requires_nonempty();
> > @@ -266,7 +276,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >         *  element of the %stack.
> >         */
> >        _GLIBCXX_NODISCARD
> > -      const_reference
> > +      _GLIBCXX26_CONSTEXPR const_reference
> >        top() const
> >        {
> >         __glibcxx_requires_nonempty();
> > @@ -282,18 +292,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >         *  to it.  The time complexity of the operation depends on the
> >         *  underlying sequence.
> >         */
> > -      void
> > +      _GLIBCXX26_CONSTEXPR void
> >        push(const value_type& __x)
> >        { c.push_back(__x); }
> >
> >  #if __cplusplus >= 201103L
> > -      void
> > +      _GLIBCXX26_CONSTEXPR void
> >        push(value_type&& __x)
> >        { c.push_back(std::move(__x)); }
> >
> >  #if __cplusplus > 201402L
> >        template<typename... _Args>
> > -       decltype(auto)
> > +       _GLIBCXX26_CONSTEXPR decltype(auto)
> >         emplace(_Args&&... __args)
> >         { return c.emplace_back(std::forward<_Args>(__args)...); }
> >  #else
> > @@ -306,7 +316,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >
> >  #if __glibcxx_containers_ranges // C++ >= 23
> >        template<__detail::__container_compatible_range<_Tp> _Rg>
> > -       void
> > +       _GLIBCXX26_CONSTEXPR void
> >         push_range(_Rg&& __rg)
> >         {
> >           if constexpr (requires {
> c.append_range(std::forward<_Rg>(__rg)); })
> > @@ -327,7 +337,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >         *  data is needed, it should be retrieved before pop() is
> >         *  called.
> >         */
> > -      void
> > +      _GLIBCXX26_CONSTEXPR void
> >        pop()
> >        {
> >         __glibcxx_requires_nonempty();
> > @@ -335,7 +345,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >        }
> >
> >  #if __cplusplus >= 201103L
> > -      void
> > +      _GLIBCXX26_CONSTEXPR void
> >        swap(stack& __s)
> >  #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or
> gnu++11
> >        noexcept(__is_nothrow_swappable<_Sequence>::value)
> > @@ -405,7 +415,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >    */
> >    template<typename _Tp, typename _Seq>
> >      _GLIBCXX_NODISCARD
> > -    inline bool
> > +    inline _GLIBCXX26_CONSTEXPR bool
>
For example this makes a lot of sense for me.

> >      operator==(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y)
> >      { return __x.c == __y.c; }
> >
> > @@ -424,49 +434,49 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >    */
> >    template<typename _Tp, typename _Seq>
> >      _GLIBCXX_NODISCARD
> > -    inline bool
> > +    inline _GLIBCXX26_CONSTEXPR 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
> > +    inline _GLIBCXX26_CONSTEXPR 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
> > +    inline _GLIBCXX26_CONSTEXPR 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
> > +    inline _GLIBCXX26_CONSTEXPR 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
> > +    inline _GLIBCXX26_CONSTEXPR 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>
> > +    inline _GLIBCXX26_CONSTEXPR 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
> > +    inline _GLIBCXX26_CONSTEXPR
> >  #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
> > diff --git a/libstdc++-v3/include/bits/version.def
> b/libstdc++-v3/include/bits/version.def
> > index b7349fdef63..81bbf0ea63a 100644
> > --- a/libstdc++-v3/include/bits/version.def
> > +++ b/libstdc++-v3/include/bits/version.def
> > @@ -1481,6 +1481,15 @@ ftms = {
> >    };
> >  };
> >
> > +ftms = {
> > +  name = constexpr_stack;
> > +  values = {
> > +    v = 202502;
> > +    cxxmin = 26;
> > +    hosted = yes;
> > +  };
> > +};
> > +
> >  ftms = {
> >    name = constrained_equality;
> >    values = {
> > diff --git a/libstdc++-v3/include/bits/version.h
> b/libstdc++-v3/include/bits/version.h
> > index 142d550279f..786db34d6be 100644
> > --- a/libstdc++-v3/include/bits/version.h
> > +++ b/libstdc++-v3/include/bits/version.h
> > @@ -1616,6 +1616,16 @@
> >  #endif /* !defined(__cpp_lib_constexpr_queue) */
> >  #undef __glibcxx_want_constexpr_queue
> >
> > +#if !defined(__cpp_lib_constexpr_stack)
> > +# if (__cplusplus >  202302L) && _GLIBCXX_HOSTED
> > +#  define __glibcxx_constexpr_stack 202502L
> > +#  if defined(__glibcxx_want_all) ||
> defined(__glibcxx_want_constexpr_stack)
> > +#   define __cpp_lib_constexpr_stack 202502L
> > +#  endif
> > +# endif
> > +#endif /* !defined(__cpp_lib_constexpr_stack) */
> > +#undef __glibcxx_want_constexpr_stack
> > +
> >  #if !defined(__cpp_lib_constrained_equality)
> >  # if (__cplusplus >  202002L) && (__glibcxx_three_way_comparison)
> >  #  define __glibcxx_constrained_equality 202411L
> > diff --git a/libstdc++-v3/include/std/stack
> b/libstdc++-v3/include/std/stack
> > index b7f9d589b37..2ace5a732fd 100644
> > --- a/libstdc++-v3/include/std/stack
> > +++ b/libstdc++-v3/include/std/stack
> > @@ -63,6 +63,7 @@
> >
> >  #define __glibcxx_want_adaptor_iterator_pair_constructor
> >  #define __glibcxx_want_containers_ranges
> > +#define __glibcxx_want_constexpr_stack
> >  #include <bits/version.h>
> >
> >  #include <deque>
> > @@ -96,6 +97,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >        // Standard declares this as template accepting unconstrained
> >        // FormatContext type.
> >        template<typename _Out>
> > +#ifdef __glibcxx_constexpr_format // C++ >= 26 && HOSTED && CXX11 string
> > +       constexpr
> > +#endif
> >         typename basic_format_context<_Out, _CharT>::iterator
> >         format(__maybe_const_adaptor& __a,
> >                basic_format_context<_Out, _CharT>& __fc) const
> > diff --git
> a/libstdc++-v3/testsuite/23_containers/headers/stack/synopsis.cc
> b/libstdc++-v3/testsuite/23_containers/headers/stack/synopsis.cc
> > index 39be405d4bd..25e6229034c 100644
> > --- a/libstdc++-v3/testsuite/23_containers/headers/stack/synopsis.cc
> > +++ b/libstdc++-v3/testsuite/23_containers/headers/stack/synopsis.cc
> > @@ -20,30 +20,36 @@
> >
> >  #include <stack>
> >
> > +#if __cplusplus > 202302L
> > +# define CONSTEXPR constexpr
> > +#else
> > +# define CONSTEXPR
> > +#endif
> > +
> >  namespace std {
> >    template <class T, class Container> class stack;
> >
> >    template <class T, class Container>
> > -    bool operator==(const stack<T, Container>& x,
> > -                    const stack<T, Container>& y);
> > +    CONSTEXPR bool
> > +    operator==(const stack<T, Container>& x, const stack<T, Container>&
> y);
> >
> >    template <class T, class Container>
> > -    bool operator< (const stack<T, Container>& x,
> > -                    const stack<T, Container>& y);
> > +    CONSTEXPR bool
> > +    operator<(const stack<T, Container>& x, const stack<T, Container>&
> y);
> >
> >    template <class T, class Container>
> > -    bool operator!=(const stack<T, Container>& x,
> > -                    const stack<T, Container>& y);
> > +    CONSTEXPR bool
> > +    operator!=(const stack<T, Container>& x, stack<T, Container>& y);
> >
> >    template <class T, class Container>
> > -    bool operator> (const stack<T, Container>& x,
> > -                    const stack<T, Container>& y);
> > +    CONSTEXPR bool
> > +    operator>(const stack<T, Container>& x, const stack<T, Container>&
> y);
> >
> >    template <class T, class Container>
> > -    bool operator>=(const stack<T, Container>& x,
> > -                    const stack<T, Container>& y);
> > +    CONSTEXPR bool
> > +    operator>=(const stack<T, Container>& x, const stack<T, Container>&
> y);
> >
> >    template <class T, class Container>
> > -    bool operator<=(const stack<T, Container>& x,
> > -                    const stack<T, Container>& y);
> > +    CONSTEXPR bool
> > +    operator<=(const stack<T, Container>& x, const stack<T, Container>&
> y);
> >  }
> > diff --git a/libstdc++-v3/testsuite/23_containers/stack/constexpr.cc
> b/libstdc++-v3/testsuite/23_containers/stack/constexpr.cc
> > new file mode 100644
> > index 00000000000..c4c96e7b537
> > --- /dev/null
> > +++ b/libstdc++-v3/testsuite/23_containers/stack/constexpr.cc
> > @@ -0,0 +1,241 @@
> > +// { dg-do compile { target c++26 } }
> > +
> > +#include <stack>
> > +
> > +#ifndef __cpp_lib_constexpr_stack
> > +# error "Feature test macro for __cpp_lib_constexpr_stack is missing in
> <stack>"
> > +#elif __cpp_lib_constexpr_stack != 202502L
> > +# error "Feature test macro for __cpp_lib_constexpr_stack has wrong
> value in <stack>"
> > +#endif
> > +
> > +#include <ranges>
> > +#include <functional>
> > +#include <vector>
> > +#include <numeric>
> > +#include <testsuite_hooks.h>
> > +#include <testsuite_iterators.h>
> > +#include <testsuite_allocator.h>
> > +
> > +using namespace __gnu_test;
> > +
> > +template<typename Cont>
> > +constexpr bool
> > +ctor_tests()
> > +{
> > +  using Tp = typename Cont::value_type;
> > +  using Alloc = typename Cont::allocator_type;
> > +
> > +  auto es = [] (std::stack<Tp, Cont> l, std::span<Tp> r) {
> > +    if (l.size() != r.size())
> > +      return false;
> > +
> > +    std::vector<Tp> s(r.begin(), r.end());
> > +    for (size_t i = s.size(); i > 0; --i) {
> > +      if (s[i-1] != l.top())
> > +       return false;
> > +      l.pop();
> > +    }
> > +    return true;
> > +  };
> > +
> > +  Cont c0;
> > +  Alloc alloc0;
> > +
> > +  std::stack<Tp, Cont> s1(c0);
> > +  VERIFY( s1.size() == 0 && s1.empty() );
> > +  s1.push(1);
> > +  s1.push(2);
> > +  VERIFY( s1.size() == 2 );
> > +
> > +  Cont c1{1, 2};
> > +  std::stack<Tp, Cont> s2(c1);
> > +  VERIFY ( s2 == s1 );
> > +  std::stack<Tp, Cont> s3(std::move(c1));
> > +  VERIFY ( s3 == s1 );
> > +
> > +  std::stack<Tp, Cont> s4(s1);
> > +  std::stack<Tp, Cont> s5(std::move(s1));
> > +  VERIFY ( s4 == s5 );
> > +
> > +  Tp rg[4] = {2, 3, 5, 7};
> > +  std::stack<Tp, Cont> s6(std::begin(rg), std::end(rg));
> > +  VERIFY ( es(s6, rg) );
> > +
> > +  VERIFY( s6.size() == std::size(rg));
> > +  VERIFY( s6.top() == 7 );
> > +  s6.pop();
> > +  VERIFY( s6.top() == 5 );
> > +  s6.pop();
> > +  VERIFY( s6.top() == 3 );
> > +  s6.pop();
> > +  VERIFY( s6.top() == 2 );
> > +  s6.pop();
> > +
> > +  std::stack<Tp, Cont> s7(alloc0);
> > +  s7.push(1);
> > +  s7.push(2);
> > +  VERIFY( s7.size() == 2 );
> > +
> > +  Cont c2{1, 2};
> > +  std::stack<Tp, Cont> s8(c2, alloc0);
> > +  VERIFY( s8 == s7 );
> > +  std::stack<Tp, Cont> s9(std::move(c2), alloc0);
> > +  VERIFY( s9 == s7 );
> > +  VERIFY( c2.empty() );
> > +
> > +  std::stack<Tp, Cont> s10(s7, alloc0);
> > +  VERIFY( s10 == s7 );
> > +  VERIFY( s10.size() == s7.size() );
> > +  VERIFY( s10.top() == s7.top() );
> > +
> > +  std::stack<Tp, Cont> s11(std::move(s7), alloc0);
> > +  VERIFY( s11 == s10 );
> > +  VERIFY( s11.size() == s10.size() );
> > +  VERIFY( s7.empty() );
> > +
> > +  std::stack<Tp, Cont> s12(std::begin(rg), std::end(rg), alloc0);
> > +  VERIFY ( es(s12, rg) );
> > +  VERIFY( s12.size() == std::size(rg));
> > +  VERIFY( s12.top() == 7 );
> > +  s12.pop();
> > +  VERIFY( s12.top() == 5 );
> > +  s12.pop();
> > +  VERIFY( s12.top() == 3 );
> > +  s12.pop();
> > +  VERIFY( s12.top() == 2 );
> > +  s12.pop();
> > +
> > +  std::stack<Tp, Cont> s13(std::from_range, rg);
> > +  VERIFY( es(s13, rg) );
> > +  std::stack<Tp, Cont> s14(std::from_range, rg, alloc0);
> > +  VERIFY( es(s14, rg) );
> > +
> > +  return true;
> > +}
> > +static_assert( ctor_tests<std::vector<int>>() );
> > +static_assert( ctor_tests<std::vector<int, SimpleAllocator<int>>>() );
> > +static_assert( ctor_tests<std::deque<int>>() );
> > +static_assert( ctor_tests<std::deque<int, SimpleAllocator<int>>>() );
> > +
> > +template<typename Range, typename Cont>
> > +constexpr void
> > +do_ranges_tests_a()
> > +{
> > +  using Tp = typename Cont::value_type;
> > +  typename Cont::allocator_type alloc;
> > +  Tp a[] {2, 3, 5, 7};
> > +
> > +  auto es = [&] (auto l, auto r) {
> > +    if (l.size() != r.size())
> > +      return false;
> > +
> > +    while (!l.empty()) {
> > +      if (l.top() != r.top())
> > +       return false;
> > +      l.pop();
> > +      r.pop();
> > +    }
> > +    return true;
> > +  };
> > +
> > +  std::stack<Tp, Cont> s1(std::from_range, Range(a, a+4));
> > +  std::stack<Tp> s2;
> > +  s2.push_range(Range(a, a+4));
> > +  VERIFY( es(s1, s2) );
> > +
> > +  std::stack<Tp, Cont> s3(std::from_range, Range(a, a+4), alloc);
> > +  std::stack<Tp, Cont> s4(std::from_range, Range(a, a+4));
> > +  VERIFY( es(s3, s4) );
> > +}
> > +
> > +template<typename Cont>
> > +constexpr bool
> > +ranges_tests()
> > +{
> > +  using Tp = typename Cont::value_type;
> > +
> > +  do_ranges_tests_a<test_forward_range<Tp>,  Cont>();
> > +  do_ranges_tests_a<test_forward_sized_range<Tp>, Cont>();
> > +  do_ranges_tests_a<
> > +    test_sized_range_sized_sent<Tp, forward_iterator_wrapper>, Cont>();
> > +
> > +  do_ranges_tests_a<test_input_range<Tp>, Cont>();
> > +  do_ranges_tests_a<test_input_sized_range<Tp>, Cont>();
> > +  do_ranges_tests_a<
> > +    test_sized_range_sized_sent<Tp, forward_iterator_wrapper>, Cont>();
> > +
> > +  do_ranges_tests_a<
> > +    test_range<Tp, input_iterator_wrapper_nocopy>, Cont>();
> > +  do_ranges_tests_a<
> > +    test_sized_range<Tp, input_iterator_wrapper_nocopy>, Cont>();
> > +  do_ranges_tests_a<
> > +    test_sized_range_sized_sent<Tp, input_iterator_wrapper_nocopy>,
> Cont>();
> > +  return true;
> > +}
> > +static_assert( ranges_tests<std::vector<int>>() );
> > +static_assert( ranges_tests<std::vector<int, SimpleAllocator<int>>>() );
> > +
> > +constexpr bool
> > +push_and_pop_test()
> > +{
> > +  std::stack<int> a;
> > +  a.push(2);
> > +  a.push(4);
> > +  VERIFY( a.top() == 4 );
> > +  a.pop();
> > +  VERIFY( a.top() == 2 );
> > +  a.pop();
> > +  VERIFY( a.empty() );
> > +  return true;
> > +}
> > +static_assert( push_and_pop_test() );
> > +
> > +constexpr bool
> > +swap_test()
> > +{
> > +  std::stack<int> a,b;
> > +  a.push(1);
> > +  b.push(2);
> > +  std::swap(a, b);
> > +  VERIFY( a.top() == 2 );
> > +  VERIFY( b.top() == 1 );
> > +  return true;
> > +}
> > +static_assert( swap_test() );
> > +
> > +constexpr bool
> > +emplace_test()
> > +{
> > +  struct S
> > +  {
> > +    int foo;
> > +    constexpr S(int i, int j) : foo{i + j} {}
> > +  };
> > +
> > +  std::stack<S> a;
> > +  const S& s = a.emplace(196883, 1);
> > +  VERIFY( a.size() == 1 );
> > +  VERIFY( a.top().foo == 196884 );
> > +  return true;
> > +}
> > +static_assert( emplace_test() );
> > +
> > +constexpr bool
> > +operator_test()
> > +{
> > +  std::stack<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() );
> > diff --git a/libstdc++-v3/testsuite/std/format/ranges/adaptors.cc
> b/libstdc++-v3/testsuite/std/format/ranges/adaptors.cc
> > index 968ac00b63e..188a6092ac7 100644
> > --- a/libstdc++-v3/testsuite/std/format/ranges/adaptors.cc
> > +++ b/libstdc++-v3/testsuite/std/format/ranges/adaptors.cc
> > @@ -167,6 +167,7 @@ test_compare()
> >  CONSTEXPR bool
> >  test_all()
> >  {
> > +  test_adaptor<std::stack>();
> >    test_adaptor<std::queue>();
> >    test_adaptor<std::priority_queue>();
> >    test_compare<char>();
> > --
> > 2.55.0
> >
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20260819/82c838d0/attachment-0001.htm>


More information about the Libstdc++ mailing list