On Tue, 2 Dec 2025 at 14:45, Yuao Ma <[email protected]> wrote:
>
> On Tue, Dec 2, 2025 at 3:51 AM Patrick Palka <[email protected]> wrote:
> >
> > On Wed, 26 Nov 2025, Yuao Ma wrote:
> >
> > > Hello world,
> > >
> > > This patch adds constexpr support to flat_map and flat_multiset in
> > > accordance with P3372R3. I have also added test cases to verify the
> > > new constexpr functionality.
> > > Tested on x86_64-linux.
> > > Please take a look when you have time. Thanks!
> >
> > Thanks for the patch!
> >
> > > Subject: [PATCH] libstdc++: constexpr flat_set and flat_multiset
> > >
> > > This patch makes flat_map and flat_multiset constexpr as part of P3372R3.
> >
> > s/flat_map/flat_set
> >
>
> Oops, fixed.
>
> > >
> > > libstdc++-v3/ChangeLog:
> > >
> > >       * include/bits/version.def: Add FTM.
> > >       * include/bits/version.h: Regenerate.
> > >       * include/std/flat_set: Add constexpr.
> > >       * testsuite/23_containers/flat_multiset/constexpr.cc: New test.
> > >       * testsuite/23_containers/flat_set/constexpr.cc: New test.
> > > ---
> > >  libstdc++-v3/include/bits/version.def         |   9 +
> > >  libstdc++-v3/include/bits/version.h           |  10 +
> > >  libstdc++-v3/include/std/flat_set             | 103 ++++++-
> > >  .../23_containers/flat_multiset/constexpr.cc  | 239 +++++++++++++++++
> > >  .../23_containers/flat_set/constexpr.cc       | 253 ++++++++++++++++++
> > >  5 files changed, 611 insertions(+), 3 deletions(-)
> > >  create mode 100644 
> > > libstdc++-v3/testsuite/23_containers/flat_multiset/constexpr.cc
> > >  create mode 100644 
> > > libstdc++-v3/testsuite/23_containers/flat_set/constexpr.cc
> > >
> > > diff --git a/libstdc++-v3/include/bits/version.def 
> > > b/libstdc++-v3/include/bits/version.def
> > > index 1fde9eef9d3..93965e914d5 100644
> > > --- a/libstdc++-v3/include/bits/version.def
> > > +++ b/libstdc++-v3/include/bits/version.def
> > > @@ -1347,6 +1347,15 @@ ftms = {
> > >    };
> > >  };
> > >
> > > +ftms = {
> > > +  name = constexpr_flat_set;
> > > +  values = {
> > > +    v = 202502;
> > > +    cxxmin = 26;
> > > +    hosted = yes;
> >
> > why hosted? flat_set isn't hosted IIRC
> >
>
> That's indeed my negligence. Fixed.
>
>
> > What do people think of supporting this as an extension in C++23 mode?
> > That way we could just specify constexpr instead of the ugly
> > _GLIBCXX26_CONSTEXPR.
> >
>
> I agree with Tomasz that this should be implemented for C++26. This
> feature has its own specific test macro indicating it belongs to
> C++26,

No, it has a feature test macro indicating the feature is supported -
that's all a feature test macro says. It doesn't say anything about
belonging to C++26.

> so implementing it for C++23 would be kind of contradictory.

Well if we implemented the feature for C++23 then we'd also set the
macro for C++23.

But it seems we don't have agreement on doing it for C++23 anyway.

>
> > > +  };
> > > +};
> > > +
> > >  ftms = {
> > >    name = constexpr_string;
> > >    values = {
> > > diff --git a/libstdc++-v3/include/bits/version.h 
> > > b/libstdc++-v3/include/bits/version.h
> > > index 2ebc48b234b..dce8351b7d6 100644
> > > --- a/libstdc++-v3/include/bits/version.h
> > > +++ b/libstdc++-v3/include/bits/version.h
> > > @@ -1495,6 +1495,16 @@
> > >  #endif /* !defined(__cpp_lib_constexpr_dynamic_alloc) */
> > >  #undef __glibcxx_want_constexpr_dynamic_alloc
> > >
> > > +#if !defined(__cpp_lib_constexpr_flat_set)
> > > +# if (__cplusplus >  202302L) && _GLIBCXX_HOSTED
> > > +#  define __glibcxx_constexpr_flat_set 202502L
> > > +#  if defined(__glibcxx_want_all) || 
> > > defined(__glibcxx_want_constexpr_flat_set)
> > > +#   define __cpp_lib_constexpr_flat_set 202502L
> > > +#  endif
> > > +# endif
> > > +#endif /* !defined(__cpp_lib_constexpr_flat_set) */
> > > +#undef __glibcxx_want_constexpr_flat_set
> > > +
> > >  #if !defined(__cpp_lib_constexpr_string)
> > >  # if (__cplusplus >= 202002L) && _GLIBCXX_USE_CXX11_ABI && 
> > > _GLIBCXX_HOSTED && (defined(__glibcxx_is_constant_evaluated))
> > >  #  define __glibcxx_constexpr_string 201907L
> > > diff --git a/libstdc++-v3/include/std/flat_set 
> > > b/libstdc++-v3/include/std/flat_set
> > > index c48340d7980..3a1f5ba10da 100644
> > > --- a/libstdc++-v3/include/std/flat_set
> > > +++ b/libstdc++-v3/include/std/flat_set
> > > @@ -33,6 +33,7 @@
> > >  #pragma GCC system_header
> > >  #endif
> > >
> > > +#define __glibcxx_want_constexpr_flat_set
> > >  #define __glibcxx_want_flat_set
> > >  #include <bits/version.h>
> > >
> > > @@ -100,50 +101,60 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >        {
> > >       container_type* _M_cont;
> > >
> > > +     _GLIBCXX26_CONSTEXPR
> > >       _ClearGuard(container_type& __cont)
> > >       : _M_cont(std::__addressof(__cont))
> > >       { }
> > >
> > > +     _GLIBCXX26_CONSTEXPR
> > >       ~_ClearGuard()
> > >       {
> > >         if (_M_cont)
> > >           _M_cont->clear();
> > >       }
> > >
> > > +     _GLIBCXX26_CONSTEXPR
> > >       void
> > >       _M_disable()
> > >       { _M_cont = nullptr; }
> > >        };
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        _ClearGuard
> > >        _M_make_clear_guard()
> > >        { return _ClearGuard{this->_M_cont}; }
> > >
> > >      public:
> > >        // constructors
> > > +      _GLIBCXX26_CONSTEXPR
> > >        _Flat_set_impl() : _Flat_set_impl(key_compare()) { }
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        explicit
> > >        _Flat_set_impl(const key_compare& __comp)
> > >        : _M_cont(), _M_comp(__comp)
> > >        { }
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        _Flat_set_impl(container_type __cont, const key_compare& __comp = 
> > > key_compare())
> > >        : _M_cont(std::move(__cont)), _M_comp(__comp)
> > >        { _M_sort_uniq(); }
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        _Flat_set_impl(__sorted_t,
> > >                    container_type __cont, const key_compare& __comp = 
> > > key_compare())
> > >        : _M_cont(std::move(__cont)), _M_comp(__comp)
> > >        { _GLIBCXX_DEBUG_ASSERT(ranges::is_sorted(_M_cont, _M_comp)); }
> > >
> > >        template<__has_input_iter_cat _InputIterator>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       _Flat_set_impl(_InputIterator __first, _InputIterator __last,
> > >                      const key_compare& __comp = key_compare())
> > >       : _M_cont(), _M_comp(__comp)
> > >       { insert(__first, __last); }
> > >
> > >        template<__has_input_iter_cat _InputIterator>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       _Flat_set_impl(__sorted_t __s,
> > >                      _InputIterator __first, _InputIterator __last,
> > >                      const key_compare& __comp = key_compare())
> > > @@ -151,20 +162,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >       { insert(__s, __first, __last); }
> > >
> > >        template<__detail::__container_compatible_range<value_type> _Rg>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       _Flat_set_impl(from_range_t, _Rg&& __rg)
> > >       : _Flat_set_impl(from_range, std::forward<_Rg>(__rg), key_compare())
> > >       { }
> > >
> > >        template<__detail::__container_compatible_range<value_type> _Rg>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       _Flat_set_impl(from_range_t, _Rg&& __rg, const key_compare& __comp)
> > >       : _Flat_set_impl(__comp)
> > >       { insert_range(std::forward<_Rg>(__rg)); }
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        _Flat_set_impl(initializer_list<value_type> __il,
> > >                    const key_compare& __comp = key_compare())
> > >        : _Flat_set_impl(__il.begin(), __il.end(), __comp)
> > >        { }
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        _Flat_set_impl(__sorted_t __s,
> > >                    initializer_list<value_type> __il,
> > >                    const key_compare& __comp = key_compare())
> > > @@ -174,23 +189,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >        // constructors with allocators
> > >
> > >        template<__allocator_for<container_type> _Alloc>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       explicit
> > >       _Flat_set_impl(const _Alloc& __a)
> > >       : _Flat_set_impl(key_compare(), __a)
> > >       { }
> > >
> > >        template<__allocator_for<container_type> _Alloc>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       _Flat_set_impl(const key_compare& __comp, const _Alloc& __a)
> > >       : _M_cont(std::make_obj_using_allocator<container_type>(__a)),
> > >         _M_comp(__comp)
> > >       { }
> > >
> > >        template<__allocator_for<container_type> _Alloc>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       _Flat_set_impl(const container_type& __cont, const _Alloc& __a)
> > >       : _Flat_set_impl(__cont, key_compare(), __a)
> > >       { }
> > >
> > >        template<__allocator_for<container_type> _Alloc>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       _Flat_set_impl(const container_type& __cont, const key_compare& 
> > > __comp,
> > >                      const _Alloc& __a)
> > >       : _M_cont(std::make_obj_using_allocator<container_type>(__a, 
> > > __cont)),
> > > @@ -198,11 +217,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >       { _M_sort_uniq(); }
> > >
> > >        template<__allocator_for<container_type> _Alloc>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       _Flat_set_impl(__sorted_t __s, const container_type& __cont, const 
> > > _Alloc& __a)
> > >       : _Flat_set_impl(__s, __cont, key_compare(), __a)
> > >       { }
> > >
> > >        template<__allocator_for<container_type> _Alloc>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       _Flat_set_impl(__sorted_t, const container_type& __cont, const 
> > > key_compare& __comp,
> > >                      const _Alloc& __a)
> > >       : _M_cont(std::make_obj_using_allocator<container_type>(__a, 
> > > __cont)),
> > > @@ -210,24 +231,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >       { _GLIBCXX_DEBUG_ASSERT(ranges::is_sorted(_M_cont, _M_comp)); }
> > >
> > >        template<__allocator_for<container_type> _Alloc>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       _Flat_set_impl(const _Derived& __x, const _Alloc& __a)
> > >       : _M_cont(std::make_obj_using_allocator<container_type>(__a, 
> > > __x._M_cont)),
> > >         _M_comp(__x._M_comp)
> > >       { }
> > >
> > >        template<__allocator_for<container_type> _Alloc>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       _Flat_set_impl(_Derived&& __x, const _Alloc& __a)
> > >       : _M_cont(std::make_obj_using_allocator<container_type>(__a, 
> > > std::move(__x._M_cont))),
> > >         _M_comp(__x._M_comp)
> > >       { }
> > >
> > >        template<__has_input_iter_cat _InputIterator, 
> > > __allocator_for<container_type> _Alloc>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       _Flat_set_impl(_InputIterator __first, _InputIterator __last,
> > >                      const _Alloc& __a)
> > >       : _Flat_set_impl(std::move(__first), std::move(__last), 
> > > key_compare(), __a)
> > >       { }
> > >
> > >        template<__has_input_iter_cat _InputIterator, 
> > > __allocator_for<container_type> _Alloc>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       _Flat_set_impl(_InputIterator __first, _InputIterator __last,
> > >                      const key_compare& __comp,
> > >                      const _Alloc& __a)
> > > @@ -235,6 +260,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >       { insert(__first, __last); }
> > >
> > >        template<__has_input_iter_cat _InputIterator, 
> > > __allocator_for<container_type> _Alloc>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       _Flat_set_impl(__sorted_t __s,
> > >                      _InputIterator __first, _InputIterator __last,
> > >                      const _Alloc& __a)
> > > @@ -242,6 +268,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >       { }
> > >
> > >        template<__has_input_iter_cat _InputIterator, 
> > > __allocator_for<container_type> _Alloc>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       _Flat_set_impl(__sorted_t __s,
> > >                      _InputIterator __first, _InputIterator __last,
> > >                      const key_compare& __comp,
> > > @@ -251,6 +278,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >
> > >        template<__detail::__container_compatible_range<value_type> _Rg,
> > >              __allocator_for<container_type> _Alloc>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       _Flat_set_impl(from_range_t, _Rg&& __rg,
> > >                      const _Alloc& __a)
> > >       : _Flat_set_impl(from_range, std::forward<_Rg>(__rg), 
> > > key_compare(), __a)
> > > @@ -258,6 +286,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >
> > >        template<__detail::__container_compatible_range<value_type> _Rg,
> > >              __allocator_for<container_type> _Alloc>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       _Flat_set_impl(from_range_t, _Rg&& __rg,
> > >                      const key_compare& __comp,
> > >                      const _Alloc& __a)
> > > @@ -265,12 +294,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >       { insert_range(std::forward<_Rg>(__rg)); }
> > >
> > >        template<__allocator_for<container_type> _Alloc>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       _Flat_set_impl(initializer_list<value_type> __il,
> > >                      const _Alloc& __a)
> > >       : _Flat_set_impl(__il, key_compare(), __a)
> > >       { }
> > >
> > >        template<__allocator_for<container_type> _Alloc>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       _Flat_set_impl(initializer_list<value_type> __il,
> > >                      const key_compare& __comp,
> > >                      const _Alloc& __a)
> > > @@ -278,6 +309,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >       { }
> > >
> > >        template<__allocator_for<container_type> _Alloc>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       _Flat_set_impl(__sorted_t __s,
> > >                      initializer_list<value_type> __il,
> > >                      const _Alloc& __a)
> > > @@ -285,6 +317,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >       { }
> > >
> > >        template<__allocator_for<container_type> _Alloc>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       _Flat_set_impl(__sorted_t __s,
> > >                      initializer_list<value_type> __il,
> > >                      const key_compare& __comp,
> > > @@ -292,6 +325,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >       : _Flat_set_impl(__s, __il.begin(), __il.end(), __comp, __a)
> > >       { }
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        _Derived&
> > >        operator=(initializer_list<value_type> __il)
> > >        {
> > > @@ -303,54 +337,66 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >        }
> > >
> > >        // iterators
> > > +      _GLIBCXX26_CONSTEXPR
> > >        const_iterator
> > >        begin() const noexcept
> > >        { return _M_cont.begin(); }
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        const_iterator
> > >        end() const noexcept
> > >        { return _M_cont.end(); }
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        const_reverse_iterator
> > >        rbegin() const noexcept
> > >        { return const_reverse_iterator(end()); }
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        const_reverse_iterator
> > >        rend() const noexcept
> > >        { return const_reverse_iterator(begin()); }
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        const_iterator
> > >        cbegin() const noexcept
> > >        { return begin(); }
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        const_iterator
> > >        cend() const noexcept
> > >        { return end(); }
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        const_reverse_iterator
> > >        crbegin() const noexcept
> > >        { return rbegin(); }
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        const_reverse_iterator
> > >        crend() const noexcept
> > >        { return rend(); }
> > >
> > >        // capacity
> > >        [[nodiscard]]
> > > +      _GLIBCXX26_CONSTEXPR
> > >        bool
> > >        empty() const noexcept
> > >        { return _M_cont.empty(); }
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        size_type
> > >        size() const noexcept
> > >        { return _M_cont.size(); }
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        size_type
> > >        max_size() const noexcept
> > >        { return _M_cont.max_size(); }
> > >
> > >        // modifiers
> > >        template<typename _Arg, typename... _Args>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       pair<iterator, bool>
> > >       _M_try_emplace(optional<const_iterator> __hint, _Arg&& __arg, 
> > > _Args&&... __args)
> > >       {
> > > @@ -410,12 +456,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >       }
> > >
> > >        template<typename... _Args>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       pair<iterator, bool>
> > >       _M_try_emplace(optional<const_iterator> __hint)
> > >       { return _M_try_emplace(__hint, value_type()); }
> > >
> > >        template<typename... _Args>
> > >       requires is_constructible_v<value_type, _Args...>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       __emplace_result_t
> > >       emplace(_Args&&... __args)
> > >       {
> > > @@ -427,39 +475,47 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >       }
> > >
> > >        template<typename... _Args>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       iterator
> > >       emplace_hint(const_iterator __position, _Args&&... __args)
> > >       { return _M_try_emplace(__position, 
> > > std::forward<_Args>(__args)...).first; }
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        __emplace_result_t
> > >        insert(const value_type& __x)
> > >        { return emplace(__x); }
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        __emplace_result_t
> > >        insert(value_type&& __x)
> > >        { return emplace(std::move(__x)); }
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        iterator
> > >        insert(const_iterator __position, const value_type& __x)
> > >        { return emplace_hint(__position, __x); }
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        iterator
> > >        insert(const_iterator __position, value_type&& __x)
> > >        { return emplace_hint(__position, std::move(__x)); }
> > >
> > >        template<typename _Arg>
> > >       requires is_constructible_v<value_type, _Arg>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       __emplace_result_t
> > >       insert(_Arg&& __x)
> > >       { return emplace(std::forward<_Arg>(__x)); }
> > >
> > >        template<typename _Arg>
> > >       requires is_constructible_v<value_type, _Arg>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       iterator
> > >       insert(const_iterator __position, _Arg&& __x)
> > >       { return emplace_hint(__position, std::forward<_Arg>(__x)); }
> > >
> > >        template<__has_input_iter_cat _InputIterator>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       void
> > >       insert(_InputIterator __first, _InputIterator __last)
> > >       {
> > > @@ -473,6 +529,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >       }
> > >
> > >        template<__has_input_iter_cat _InputIterator>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       void
> > >       insert(__sorted_t, _InputIterator __first, _InputIterator __last)
> > >       {
> > > @@ -485,6 +542,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >       }
> > >
> > >        template<__detail::__container_compatible_range<value_type> _Rg>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       void
> > >       insert_range(_Rg&& __rg)
> > >       {
> > > @@ -511,14 +569,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >         __guard._M_disable();
> > >       }
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        void
> > >        insert(initializer_list<value_type> __il)
> > >        { insert(__il.begin(), __il.end()); }
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        void
> > >        insert(__sorted_t __s, initializer_list<value_type> __il)
> > >        { insert(__s, __il.begin(), __il.end()); }
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        container_type
> > >        extract() &&
> > >        {
> > > @@ -526,6 +587,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >       return std::move(_M_cont);
> > >        }
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        void
> > >        replace(container_type&& __cont)
> > >        {
> > > @@ -535,10 +597,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >       __guard._M_disable();
> > >        }
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        iterator
> > >        erase(const_iterator __position)
> > >        { return _M_cont.erase(__position); }
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        size_type
> > >        erase(const key_type& __x)
> > >        { return erase<const key_type&>(__x); }
> > > @@ -548,6 +612,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >         || (__transparent_comparator<_Compare>
> > >             && !is_convertible_v<_Key2, iterator>
> > >             && !is_convertible_v<_Key2, const_iterator>)
> > > +     _GLIBCXX26_CONSTEXPR
> > >       size_type
> > >       erase(_Key2&& __x)
> > >       {
> > > @@ -557,10 +622,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >         return __n;
> > >       }
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        iterator
> > >        erase(const_iterator __first, const_iterator __last)
> > >        { return _M_cont.erase(__first, __last); }
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        void
> > >        swap(_Derived& __x) noexcept
> > >        {
> > > @@ -569,28 +636,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >       swap(_M_comp, __x._M_comp);
> > >        }
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        void
> > >        clear() noexcept
> > >        { _M_cont.clear(); }
> > >
> > >        // observers
> > >        [[nodiscard]]
> > > +      _GLIBCXX26_CONSTEXPR
> > >        key_compare
> > >        key_comp() const
> > >        { return _M_comp; }
> > >
> > >        [[nodiscard]]
> > > +      _GLIBCXX26_CONSTEXPR
> > >        value_compare
> > >        value_comp() const
> > >        { return _M_comp; }
> > >
> > >        // set operations
> > >        [[nodiscard]]
> > > +      _GLIBCXX26_CONSTEXPR
> > >        iterator
> > >        find(const key_type& __x)
> > >        { return find<key_type>(__x); }
> > >
> > >        [[nodiscard]]
> > > +      _GLIBCXX26_CONSTEXPR
> > >        const_iterator
> > >        find(const key_type& __x) const
> > >        { return find<key_type>(__x); }
> > > @@ -598,6 +670,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >        template<typename _Key2>
> > >       requires same_as<_Key2, _Key> || __transparent_comparator<_Compare>
> > >       [[nodiscard]]
> > > +     _GLIBCXX26_CONSTEXPR
> > >       iterator
> > >       find(const _Key2& __x)
> > >       {
> > > @@ -611,6 +684,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >        template<typename _Key2>
> > >       requires same_as<_Key2, _Key> || __transparent_comparator<_Compare>
> > >       [[nodiscard]]
> > > +     _GLIBCXX26_CONSTEXPR
> > >       const_iterator
> > >       find(const _Key2& __x) const
> > >       {
> > > @@ -622,6 +696,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >       }
> > >
> > >        [[nodiscard]]
> > > +      _GLIBCXX26_CONSTEXPR
> > >        size_type
> > >        count(const key_type& __x) const
> > >        { return count<key_type>(__x); }
> > > @@ -629,6 +704,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >        template<typename _Key2>
> > >       requires same_as<_Key2, _Key> || __transparent_comparator<_Compare>
> > >       [[nodiscard]]
> > > +     _GLIBCXX26_CONSTEXPR
> > >       size_type
> > >       count(const _Key2& __x) const
> > >       {
> > > @@ -642,6 +718,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >       }
> > >
> > >        [[nodiscard]]
> > > +      _GLIBCXX26_CONSTEXPR
> > >        bool
> > >        contains(const key_type& __x) const
> > >        { return contains<key_type>(__x); }
> > > @@ -649,16 +726,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >        template<typename _Key2>
> > >       requires same_as<_Key2, _Key> || __transparent_comparator<_Compare>
> > >       [[nodiscard]]
> > > +     _GLIBCXX26_CONSTEXPR
> > >       bool
> > >       contains(const _Key2& __x) const
> > >       { return find(__x) != cend(); }
> > >
> > >        [[nodiscard]]
> > > +      _GLIBCXX26_CONSTEXPR
> > >        iterator
> > >        lower_bound(const key_type& __x)
> > >        { return lower_bound<key_type>(__x); }
> > >
> > >        [[nodiscard]]
> > > +      _GLIBCXX26_CONSTEXPR
> > >        const_iterator
> > >        lower_bound(const key_type& __x) const
> > >        { return lower_bound<key_type>(__x); }
> > > @@ -666,6 +746,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >        template<typename _Key2>
> > >       requires same_as<_Key2, _Key> || __transparent_comparator<_Compare>
> > >       [[nodiscard]]
> > > +     _GLIBCXX26_CONSTEXPR
> > >       iterator
> > >       lower_bound(const _Key2& __x)
> > >       { return std::lower_bound(begin(), end(), __x, _M_comp); }
> > > @@ -673,16 +754,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >        template<typename _Key2>
> > >       requires same_as<_Key2, _Key> || __transparent_comparator<_Compare>
> > >       [[nodiscard]]
> > > +     _GLIBCXX26_CONSTEXPR
> > >       const_iterator
> > >       lower_bound(const _Key2& __x) const
> > >       { return std::lower_bound(begin(), end(), __x, _M_comp); }
> > >
> > >        [[nodiscard]]
> > > +      _GLIBCXX26_CONSTEXPR
> > >        iterator
> > >        upper_bound(const key_type& __x)
> > >        { return upper_bound<key_type>(__x); }
> > >
> > >        [[nodiscard]]
> > > +      _GLIBCXX26_CONSTEXPR
> > >        const_iterator
> > >        upper_bound(const key_type& __x) const
> > >        { return upper_bound<key_type>(__x); }
> > > @@ -690,6 +774,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >        template<typename _Key2>
> > >       requires same_as<_Key2, _Key> || __transparent_comparator<_Compare>
> > >       [[nodiscard]]
> > > +     _GLIBCXX26_CONSTEXPR
> > >       iterator
> > >       upper_bound(const _Key2& __x)
> > >       { return std::upper_bound(begin(), end(), __x, _M_comp); }
> > > @@ -697,16 +782,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >        template<typename _Key2>
> > >       requires same_as<_Key2, _Key> || __transparent_comparator<_Compare>
> > >       [[nodiscard]]
> > > +     _GLIBCXX26_CONSTEXPR
> > >       const_iterator
> > >       upper_bound(const _Key2& __x) const
> > >       { return std::upper_bound(begin(), end(), __x, _M_comp); }
> > >
> > >        [[nodiscard]]
> > > +      _GLIBCXX26_CONSTEXPR
> > >        pair<iterator, iterator>
> > >        equal_range(const key_type& __x)
> > >        { return equal_range<key_type>(__x); }
> > >
> > >        [[nodiscard]]
> > > +      _GLIBCXX26_CONSTEXPR
> > >        pair<const_iterator, const_iterator>
> > >        equal_range(const key_type& __x) const
> > >        { return equal_range<key_type>(__x); }
> > > @@ -714,6 +802,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >        template<typename _Key2>
> > >       requires same_as<_Key2, _Key> || __transparent_comparator<_Compare>
> > >       [[nodiscard]]
> > > +     _GLIBCXX26_CONSTEXPR
> > >       pair<iterator, iterator>
> > >       equal_range(const _Key2& __x)
> > >       { return std::equal_range(begin(), end(), __x, _M_comp); }
> > > @@ -721,18 +810,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >        template<typename _Key2>
> > >       requires same_as<_Key2, _Key> || __transparent_comparator<_Compare>
> > >       [[nodiscard]]
> > > +     _GLIBCXX26_CONSTEXPR
> > >       pair<const_iterator, const_iterator>
> > >       equal_range(const _Key2& __x) const
> > >       { return std::equal_range(begin(), end(), __x, _M_comp); }
> > >
> > >        [[nodiscard]]
> > > -      friend bool
> > > +      friend _GLIBCXX26_CONSTEXPR bool
> > >        operator==(const _Derived& __x, const _Derived& __y)
> > >        { return std::equal(__x.begin(), __x.end(), __y.begin(), 
> > > __y.end()); }
> > >
> > >        template<typename _Up = value_type>
> > >       [[nodiscard]]
> > > -     friend __detail::__synth3way_t<_Up>
> > > +     friend _GLIBCXX26_CONSTEXPR __detail::__synth3way_t<_Up>
> > >       operator<=>(const _Derived& __x, const _Derived& __y)
> > >       {
> > >         return std::lexicographical_compare_three_way(__x.begin(), 
> > > __x.end(),
> > > @@ -740,11 +830,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >                                                       
> > > __detail::__synth3way);
> > >       }
> > >
> > > -      friend void
> > > +      friend _GLIBCXX26_CONSTEXPR void
> > >        swap(_Derived& __x, _Derived& __y) noexcept
> > >        { return __x.swap(__y); }
> > >
> > >        template<typename _Predicate>
> > > +     _GLIBCXX26_CONSTEXPR
> > >       size_type
> > >       _M_erase_if(_Predicate __pred)
> > >       {
> > > @@ -762,6 +853,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >        container_type _M_cont;
> > >        [[no_unique_address]] _Compare _M_comp;
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        void
> > >        _M_sort_uniq()
> > >        {
> > > @@ -770,13 +862,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >         _M_unique();
> > >        }
> > >
> > > +      _GLIBCXX26_CONSTEXPR
> > >        void
> > >        _M_unique() requires (!_Multi)
> > >        {
> > >       struct __key_equiv
> > >       {
> > > +       _GLIBCXX26_CONSTEXPR
> > >         __key_equiv(key_compare __c) : _M_comp(__c) { }
> > >
> > > +       _GLIBCXX26_CONSTEXPR
> > >         bool
> > >         operator()(const_reference __x, const_reference __y) const
> > >         { return !_M_comp(__x, __y) && !_M_comp(__y, __x); }
> > > @@ -934,6 +1029,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >
> > >    template<typename _Key, typename _Compare, typename _KeyContainer,
> > >          typename _Predicate>
> > > +    _GLIBCXX26_CONSTEXPR
> > >      typename flat_set<_Key, _Compare, _KeyContainer>::size_type
> > >      erase_if(flat_set<_Key, _Compare, _KeyContainer>& __c, _Predicate 
> > > __pred)
> > >      { return __c._M_erase_if(std::move(__pred)); }
> > > @@ -1081,6 +1177,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> > >
> > >    template<typename _Key, typename _Compare, typename _KeyContainer,
> > >          typename _Predicate>
> > > +    _GLIBCXX26_CONSTEXPR
> > >      typename flat_multiset<_Key, _Compare, _KeyContainer>::size_type
> > >      erase_if(flat_multiset<_Key, _Compare, _KeyContainer>& __c, 
> > > _Predicate __pred)
> > >      { return __c._M_erase_if(std::move(__pred)); }
> > > diff --git 
> > > a/libstdc++-v3/testsuite/23_containers/flat_multiset/constexpr.cc 
> > > b/libstdc++-v3/testsuite/23_containers/flat_multiset/constexpr.cc
> > > new file mode 100644
> > > index 00000000000..860b7660809
> > > --- /dev/null
> > > +++ b/libstdc++-v3/testsuite/23_containers/flat_multiset/constexpr.cc
> > > @@ -0,0 +1,239 @@
> > > +// { dg-do run { target c++26 } }
> >
> > I'd expect constexpr tests to be compile-only.
> >
>
> Fixed.
>
> > Besides that looks good! Thanks for the comprehensive tests.
> >
>
> Thank you for the review! If there are no further objections, I plan
> to commit the patch this weekend.

Please wait for approval from me (or a global reviewer for the whole
of gcc). Patrick is not listed with approval rights in the maintainers
file.


Reply via email to