On Thu, 17 Jul 2025, Tomasz Kamiński wrote:

> From: Jonathan Wakely <jwak...@redhat.com>
> 
> Implement std::inplace_vector as specified in P0843R14, without follow
> up papers, in particular P3074R7 (trivial unions). In consequence
> inplace_vector<T, N> can be used inside constant evaluations only
> if T is trivial or N is equal to zero.
> 
> We provide a separate specialization for inplace_vector<T, 0> to meet
> the requirements of N5008 [inplace.vector.overview] p5. In particular
> objects of such types needs to be empty.
> 
> To allow constexpr variable of inplace_vector v, where v.size() < 
> v.capacity(),
> we need to guaranteed that all elements of the storage array are initialized,
> even ones in range [v.data() + v.size(), v.data() + v.capacity()). This is
> perfomed by _M_init function, that is alled by each constructored. By storing
> the array in anonymous union, we can perform this initialization in constant
> evaluation, avoiding the impact on runtime path.
> 
> The size() function conveys the information that _M_size <= _Nm to compiler,
> by calling __builtin_unreachable(). In particular this allows us to eliminate
> FP warnings by using _Nm - size() instead of _Nm - _M_size, when computing
> available elements.
> 
> However, we still have one -Waggressive-loop-optimizations (to best of our
> knowledge false-positive warning produced in cons/from_range.cc and
> cons/throws.cc. Currently it is pruned using dg-prune-output and tracked by
> PR121143.
> 
> The included test cover almost all code paths at runtime, however some
> compile time evaluation test are not yet implemented:
> * operations on range, they depenend on making testsuite_iterators constexpr
> * negative test for invoking operations with preconditions at compile time,
>   especially for zero size specialization.
> 
>       PR libstdc++/119137
> 
> libstdc++-v3/ChangeLog:
> 
>       * doc/doxygen/user.cfg.in (INPUT): Add new header.
>       * include/Makefile.am: Add new header.
>       * include/Makefile.in: Regenerate.
>       * include/bits/stl_iterator_base_types.h (__any_input_iterator):
>       Define.
>       * include/bits/version.def (inplace_vector): Define.
>       * include/bits/version.h: Regenerate.
>       * include/precompiled/stdc++.h: Include new header.
>       * src/c++23/std.cc.in: Export contents if new header.
>       * include/std/inplace_vector: New file.
>       * testsuite/23_containers/inplace_vector/access/capacity.cc: New file.
>       * testsuite/23_containers/inplace_vector/access/elem.cc: New file.
>       * testsuite/23_containers/inplace_vector/access/elem_neg.cc: New file.
>       * testsuite/23_containers/inplace_vector/cons/1.cc: New file.
>       * testsuite/23_containers/inplace_vector/cons/from_range.cc: New file.
>       * testsuite/23_containers/inplace_vector/cons/throws.cc: New file.
>       * testsuite/23_containers/inplace_vector/copy.cc: New file.
>       * testsuite/23_containers/inplace_vector/erasure.cc: New file.
>       * testsuite/23_containers/inplace_vector/modifiers/assign.cc: New file.
>       * testsuite/23_containers/inplace_vector/modifiers/erase.cc: New file.
>       * testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc:
>       New file.
>       * testsuite/23_containers/inplace_vector/modifiers/single_insert.cc:
>       New file.
>       * testsuite/23_containers/inplace_vector/move.cc: New file.
>       * testsuite/23_containers/inplace_vector/relops.cc: New file.
>       * testsuite/23_containers/inplace_vector/version.cc: New file.
>       * testsuite/util/testsuite_iterators.h (input_iterator_wrapper::base):
>       Define.
> 
> Reviewed-by: Patrick Palka <ppa...@redhat.com>
> Reviewed-by: Jonathan Wakely <jwak...@redhat.com>
> Co-authored-by: Tomasz Kamiński <tkami...@redhat.com>
> Signed-off-by: Tomasz Kamiński <tkami...@redhat.com>
> ---
> v2 hopefully addressed all the comments from Patrick review,
> except making _S_distance a free functions.
> The detail::__input_iterator is moved to stl_iterator_base_types.h,
> and renamed any_input_iterator.
> 
>  libstdc++-v3/doc/doxygen/user.cfg.in          |    1 +
>  libstdc++-v3/include/Makefile.am              |    1 +
>  libstdc++-v3/include/Makefile.in              |    1 +
>  .../include/bits/stl_iterator_base_types.h    |    5 +
>  libstdc++-v3/include/bits/version.def         |    8 +
>  libstdc++-v3/include/bits/version.h           |   10 +
>  libstdc++-v3/include/precompiled/stdc++.h     |    1 +
>  libstdc++-v3/include/std/inplace_vector       | 1376 +++++++++++++++++
>  libstdc++-v3/src/c++23/std.cc.in              |   10 +-
>  .../inplace_vector/access/capacity.cc         |   51 +
>  .../inplace_vector/access/elem.cc             |  103 ++
>  .../inplace_vector/access/elem_neg.cc         |   29 +
>  .../23_containers/inplace_vector/cons/1.cc    |  385 +++++
>  .../inplace_vector/cons/from_range.cc         |  186 +++
>  .../inplace_vector/cons/throws.cc             |  131 ++
>  .../23_containers/inplace_vector/copy.cc      |  247 +++
>  .../23_containers/inplace_vector/erasure.cc   |   49 +
>  .../inplace_vector/modifiers/assign.cc        |  386 +++++
>  .../inplace_vector/modifiers/erase.cc         |  117 ++
>  .../inplace_vector/modifiers/multi_insert.cc  |  611 ++++++++
>  .../inplace_vector/modifiers/single_insert.cc |  215 +++
>  .../23_containers/inplace_vector/move.cc      |  358 +++++
>  .../23_containers/inplace_vector/relops.cc    |   60 +
>  .../23_containers/inplace_vector/version.cc   |   20 +
>  .../testsuite/util/testsuite_iterators.h      |    6 +
>  25 files changed, 4366 insertions(+), 1 deletion(-)
>  create mode 100644 libstdc++-v3/include/std/inplace_vector
>  create mode 100644 
> libstdc++-v3/testsuite/23_containers/inplace_vector/access/capacity.cc
>  create mode 100644 
> libstdc++-v3/testsuite/23_containers/inplace_vector/access/elem.cc
>  create mode 100644 
> libstdc++-v3/testsuite/23_containers/inplace_vector/access/elem_neg.cc
>  create mode 100644 
> libstdc++-v3/testsuite/23_containers/inplace_vector/cons/1.cc
>  create mode 100644 
> libstdc++-v3/testsuite/23_containers/inplace_vector/cons/from_range.cc
>  create mode 100644 
> libstdc++-v3/testsuite/23_containers/inplace_vector/cons/throws.cc
>  create mode 100644 
> libstdc++-v3/testsuite/23_containers/inplace_vector/copy.cc
>  create mode 100644 
> libstdc++-v3/testsuite/23_containers/inplace_vector/erasure.cc
>  create mode 100644 
> libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/assign.cc
>  create mode 100644 
> libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/erase.cc
>  create mode 100644 
> libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc
>  create mode 100644 
> libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/single_insert.cc
>  create mode 100644 
> libstdc++-v3/testsuite/23_containers/inplace_vector/move.cc
>  create mode 100644 
> libstdc++-v3/testsuite/23_containers/inplace_vector/relops.cc
>  create mode 100644 
> libstdc++-v3/testsuite/23_containers/inplace_vector/version.cc
> 
> diff --git a/libstdc++-v3/doc/doxygen/user.cfg.in 
> b/libstdc++-v3/doc/doxygen/user.cfg.in
> index 536e035b023..8969bb8b948 100644
> --- a/libstdc++-v3/doc/doxygen/user.cfg.in
> +++ b/libstdc++-v3/doc/doxygen/user.cfg.in
> @@ -869,6 +869,7 @@ INPUT                  = 
> @srcdir@/doc/doxygen/doxygroups.cc \
>                           include/functional \
>                           include/future \
>                           include/generator \
> +                         include/inplace_vector \
>                           include/iomanip \
>                           include/ios \
>                           include/iosfwd \
> diff --git a/libstdc++-v3/include/Makefile.am 
> b/libstdc++-v3/include/Makefile.am
> index cc402f0648f..6f248fe48cb 100644
> --- a/libstdc++-v3/include/Makefile.am
> +++ b/libstdc++-v3/include/Makefile.am
> @@ -77,6 +77,7 @@ std_headers = \
>       ${std_srcdir}/forward_list \
>       ${std_srcdir}/fstream \
>       ${std_srcdir}/future \
> +     ${std_srcdir}/inplace_vector \
>       ${std_srcdir}/iomanip \
>       ${std_srcdir}/ios \
>       ${std_srcdir}/iosfwd \
> diff --git a/libstdc++-v3/include/Makefile.in 
> b/libstdc++-v3/include/Makefile.in
> index 0ef8564f238..014466fc40b 100644
> --- a/libstdc++-v3/include/Makefile.in
> +++ b/libstdc++-v3/include/Makefile.in
> @@ -433,6 +433,7 @@ std_freestanding = \
>  @GLIBCXX_HOSTED_TRUE@        ${std_srcdir}/forward_list \
>  @GLIBCXX_HOSTED_TRUE@        ${std_srcdir}/fstream \
>  @GLIBCXX_HOSTED_TRUE@        ${std_srcdir}/future \
> +@GLIBCXX_HOSTED_TRUE@        ${std_srcdir}/inplace_vector \
>  @GLIBCXX_HOSTED_TRUE@        ${std_srcdir}/iomanip \
>  @GLIBCXX_HOSTED_TRUE@        ${std_srcdir}/ios \
>  @GLIBCXX_HOSTED_TRUE@        ${std_srcdir}/iosfwd \
> diff --git a/libstdc++-v3/include/bits/stl_iterator_base_types.h 
> b/libstdc++-v3/include/bits/stl_iterator_base_types.h
> index a67d7bd1931..71da909613e 100644
> --- a/libstdc++-v3/include/bits/stl_iterator_base_types.h
> +++ b/libstdc++-v3/include/bits/stl_iterator_base_types.h
> @@ -257,6 +257,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>    template<typename _InIter>
>      concept __has_input_iter_cat
>        = is_convertible_v<__iter_category_t<_InIter>, input_iterator_tag>;
> +
> +  // Is a Cpp17InputIterator or satisfies std::input_iterator.
> +  template<typename _InIterator>
> +    concept __any_input_iterator
> +      = input_iterator<_InIterator> || __has_input_iter_cat<_InIterator>;
>  #endif
>  
>    template<typename _It,
> diff --git a/libstdc++-v3/include/bits/version.def 
> b/libstdc++-v3/include/bits/version.def
> index 2f70a529927..dbe2cb8f175 100644
> --- a/libstdc++-v3/include/bits/version.def
> +++ b/libstdc++-v3/include/bits/version.def
> @@ -1988,6 +1988,14 @@ ftms = {
>    };
>  };
>  
> +ftms = {
> +  name = inplace_vector;
> +  values = {
> +    v = 202406;
> +    cxxmin = 26;
> +  };
> +};
> +
>  ftms = {
>    name = indirect;
>    values = {
> diff --git a/libstdc++-v3/include/bits/version.h 
> b/libstdc++-v3/include/bits/version.h
> index 8e0ae682251..7bb6016df68 100644
> --- a/libstdc++-v3/include/bits/version.h
> +++ b/libstdc++-v3/include/bits/version.h
> @@ -2229,6 +2229,16 @@
>  #endif /* !defined(__cpp_lib_modules) && defined(__glibcxx_want_modules) */
>  #undef __glibcxx_want_modules
>  
> +#if !defined(__cpp_lib_inplace_vector)
> +# if (__cplusplus >  202302L)
> +#  define __glibcxx_inplace_vector 202406L
> +#  if defined(__glibcxx_want_all) || defined(__glibcxx_want_inplace_vector)
> +#   define __cpp_lib_inplace_vector 202406L
> +#  endif
> +# endif
> +#endif /* !defined(__cpp_lib_inplace_vector) && 
> defined(__glibcxx_want_inplace_vector) */
> +#undef __glibcxx_want_inplace_vector
> +
>  #if !defined(__cpp_lib_indirect)
>  # if (__cplusplus >  202302L) && _GLIBCXX_HOSTED
>  #  define __glibcxx_indirect 202502L
> diff --git a/libstdc++-v3/include/precompiled/stdc++.h 
> b/libstdc++-v3/include/precompiled/stdc++.h
> index e7d89c92704..733a5e5fb0b 100644
> --- a/libstdc++-v3/include/precompiled/stdc++.h
> +++ b/libstdc++-v3/include/precompiled/stdc++.h
> @@ -237,6 +237,7 @@
>  #endif
>  
>  #if __cplusplus > 202302L
> +#include <inplace_vector>
>  #include <text_encoding>
>  #include <stdbit.h>
>  #include <stdckdint.h>
> diff --git a/libstdc++-v3/include/std/inplace_vector 
> b/libstdc++-v3/include/std/inplace_vector
> new file mode 100644
> index 00000000000..3fb38f383fb
> --- /dev/null
> +++ b/libstdc++-v3/include/std/inplace_vector
> @@ -0,0 +1,1376 @@
> +// Sequence container with fixed capacity -*- C++ -*-
> +
> +// Copyright The GNU Toolchain Authors.
> +//
> +// 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/>.
> +
> +/** @file include/inplace_vector
> + *  This is a Standard C++ Library header.
> + *  @ingroup sequences
> + */
> +
> +#ifndef _GLIBCXX_INPLACE_VECTOR
> +#define _GLIBCXX_INPLACE_VECTOR 1
> +
> +#pragma GCC system_header
> +
> +#define __glibcxx_want_inplace_vector
> +#include <bits/version.h>
> +
> +#ifdef __glibcxx_inplace_vector // C++ >= 26 
> +#include <compare>
> +#include <initializer_list>
> +#include <bits/range_access.h>
> +#include <bits/ranges_base.h> // borrowed_iterator_t, 
> __detail::__container_compatible_range
> +#include <bits/ranges_util.h> // subrange
> +#include <bits/ranges_uninitialized.h>
> +#include <bits/refwrap.h>
> +#include <bits/stl_construct.h>
> +#include <bits/stl_uninitialized.h>
> +#include <bits/stl_algo.h> // rotate
> +
> +namespace std _GLIBCXX_VISIBILITY(default)
> +{
> +_GLIBCXX_BEGIN_NAMESPACE_VERSION
> +
> +  // [indirect], class template indirect
> +  template<typename _Tp, size_t _Nm>
> +    class inplace_vector
> +    {
> +    public:
> +
> +      // types:
> +      using value_type             = _Tp;
> +      using pointer                = _Tp*;
> +      using const_pointer          = const _Tp*;
> +      using reference              = value_type&;
> +      using const_reference        = const value_type&;
> +      using size_type              = size_t;
> +      using difference_type        = ptrdiff_t;
> +      using iterator
> +     = __gnu_cxx::__normal_iterator<_Tp*, inplace_vector>;
> +      using const_iterator
> +     = __gnu_cxx::__normal_iterator<const _Tp*, inplace_vector>;
> +      using reverse_iterator       = std::reverse_iterator<iterator>;
> +      using const_reverse_iterator = std::reverse_iterator<const_iterator>;
> +
> +      // [containers.sequences.inplace.vector.cons], construct/copy/destroy
> +      constexpr
> +      inplace_vector() noexcept
> +      { _M_init(); }
> +
> +      constexpr explicit
> +      inplace_vector(size_type __n)
> +      {
> +     _M_init();
> +     _S_reserve(__n);
> +     std::uninitialized_value_construct_n(data(), __n);
> +     _M_size = __n;
> +      }
> +
> +      constexpr
> +      inplace_vector(size_type __n, const _Tp& __value)
> +      {
> +     _M_init();
> +     _S_reserve(__n);
> +     std::uninitialized_fill_n(data(), __n, __value);
> +     _M_size = __n;
> +      }
> +
> +      template<__any_input_iterator _InputIterator>
> +     constexpr
> +     inplace_vector(_InputIterator __first, _InputIterator __last)
> +     : inplace_vector()
> +     {
> +       if (const auto __n = _S_distance(__first, __last))
> +         {
> +           _S_reserve(__n);
> +           std::uninitialized_copy(__first, __last, data());
> +           _M_size = __n;
> +         }
> +       else
> +         {
> +           while (__first != __last)
> +             emplace_back(*__first++);
> +         }
> +     }
> +
> +      template <__detail::__container_compatible_range<_Tp> _Rg>
> +     constexpr
> +     inplace_vector(from_range_t, _Rg&& __rg)
> +     : inplace_vector()
> +     { append_range(__rg); }
> +
> +      constexpr
> +      inplace_vector(initializer_list<_Tp> __il)
> +      {
> +     _M_init();
> +     _S_reserve(__il.size());
> +     std::uninitialized_copy(__il.begin(), __il.end(), data());
> +     _M_size = __il.size();
> +      }
> +
> +      inplace_vector(const inplace_vector&)
> +     requires is_trivially_copy_constructible_v<_Tp>
> +     = default;
> +
> +      constexpr
> +      inplace_vector(const inplace_vector& __other)
> +      noexcept(is_nothrow_copy_constructible_v<_Tp>)
> +      {
> +     _M_init();
> +     std::uninitialized_copy(__other.begin(), __other.end(), data());
> +     _M_size = __other.size();
> +      }
> +
> +      inplace_vector(inplace_vector&&)
> +     requires is_trivially_move_constructible_v<_Tp>
> +     = default;
> +
> +      constexpr
> +      inplace_vector(inplace_vector&& __other)
> +      noexcept(is_nothrow_move_constructible_v<_Tp>)
> +      {
> +     _M_init();
> +     std::uninitialized_move(__other.begin(), __other.end(), data());
> +     _M_size = __other.size();
> +      }
> +
> +      ~inplace_vector()
> +     requires is_trivially_destructible_v<_Tp>
> +     = default;
> +
> +      constexpr
> +      ~inplace_vector()
> +      { clear(); }
> +
> +      inplace_vector&
> +      operator=(const inplace_vector&)
> +     requires is_trivially_copy_assignable_v<_Tp>
> +                && is_trivially_copy_constructible_v<_Tp>
> +                && is_trivially_destructible_v<_Tp>
> +     = default;
> +
> +      constexpr inplace_vector&
> +      operator=(const inplace_vector& __other)
> +      noexcept(is_nothrow_copy_assignable_v<_Tp>
> +              && is_nothrow_copy_constructible_v<_Tp>)
> +      {
> +     assign(__other.begin(), __other.end());

Do we need to worry about self-assignment here?  IIUC it's a
precondition violation to call assign with an iterator into the
container being assigned to.  LGTM other than that.

> +     return *this;
> +      }
> +
> +      inplace_vector&
> +      operator=(inplace_vector&&)
> +     requires is_trivially_move_assignable_v<_Tp>
> +                && is_trivially_move_constructible_v<_Tp>
> +                && is_trivially_destructible_v<_Tp>
> +     = default;
> +
> +      constexpr inplace_vector&
> +      operator=(inplace_vector&& __other)
> +      noexcept(is_nothrow_move_assignable_v<_Tp>
> +              && is_nothrow_move_constructible_v<_Tp>)
> +      {
> +     assign(std::make_move_iterator(__other.begin()),
> +            std::make_move_iterator(__other.end()));
> +     return *this;
> +      }
> +
> +      constexpr inplace_vector&
> +      operator=(initializer_list<_Tp> __il)
> +      {
> +     assign(__il.begin(), __il.end());
> +     return *this;
> +      }
> +
> +      template<__any_input_iterator _InputIterator>
> +     constexpr void
> +     assign(_InputIterator __first, _InputIterator __last)
> +     {
> +       if (const auto __n = _S_distance(__first, __last))
> +         {
> +           _S_reserve(__n);
> +           if (_M_size <= __n)
> +             {
> +               for (size_t __i = 0; __i < _M_size; ++__i, (void)++__first)
> +                 _M_elems[__i] = *__first;
> +               std::uninitialized_copy(__first, __last, end());
> +             }
> +           else
> +             std::destroy(std::copy(__first, __last, begin()), end());
> +           _M_size = __n;
> +         }
> +       else
> +         {
> +           size_t __i = 0;
> +           for (;__first != __last && __i < _M_size; ++__first)
> +             _M_elems[__i++] = *__first;
> +           if (__first == __last)
> +             {
> +               std::_Destroy_n(data() + __i, _M_size - __i);
> +               _M_size = __i;
> +             }
> +           else
> +             {
> +               while (__first != __last)
> +                 emplace_back(*__first++);
> +             }
> +         }
> +     }
> +
> +      template<__detail::__container_compatible_range<_Tp> _Rg>
> +     constexpr void
> +     assign_range(_Rg&& __rg)
> +     {
> +       if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
> +         {
> +           const auto __sz = ranges::distance(__rg);
> +           if (__sz > _Nm)
> +             __throw_bad_alloc();
> +           if (__sz <= size())
> +             {
> +               ranges::copy_n(ranges::begin(__rg), __sz, data());
> +               std::destroy(data() + __sz, data() + _M_size);
> +             }
> +           else
> +             {
> +               auto [__in, __out] = ranges::copy_n(
> +                                      ranges::begin(__rg), _M_size,
> +                                      data());
> +               ranges::uninitialized_copy(
> +                 std::move(__in), ranges::end(__rg),
> +                 __out, unreachable_sentinel);
> +             }
> +           _M_size = __sz;
> +         }
> +       else
> +         {
> +           auto __in = ranges::begin(__rg);
> +           auto __end = ranges::end(__rg);
> +           size_type __n = 0;
> +           for (; __n < _Nm && __in != __end; ++__in)
> +             _M_elems[__n++] = *__in;
> +
> +           if (__in == __end)
> +             {
> +               std::destroy(data() + __n, data() + _M_size);
> +               _M_size = __n;
> +               return;
> +             }
> +           else if (__n < _Nm)
> +             {
> +               auto __res = ranges::uninitialized_copy(
> +                             std::move(__in), __end,
> +                             data() + __n, data() + _Nm);
> +               _M_size = __res.out - data();
> +               if (__res.in == ranges::end(__rg))
> +                 return;
> +             }
> +           __throw_bad_alloc();
> +         }
> +     }
> +
> +      constexpr void
> +      assign(size_type __n, const _Tp& __u)
> +      {
> +     _S_reserve(__n);
> +     if (_M_size <= __n)
> +       std::uninitialized_fill_n(std::fill_n(data(), _M_size, __u),
> +                                 __n - _M_size, __u);
> +     else
> +       std::destroy_n(std::fill_n(data(), __n, __u), _M_size - __n);
> +     _M_size = __n;
> +      }
> +
> +      constexpr void
> +      assign(initializer_list<_Tp> __il)
> +      { assign(__il.begin(), __il.end()); }
> +
> +      // iterators
> +      [[nodiscard]]
> +      constexpr iterator
> +      begin() noexcept { return iterator(data()); }
> +
> +      [[nodiscard]]
> +      constexpr const_iterator
> +      begin() const noexcept { return const_iterator(data()); }
> +
> +      [[nodiscard]]
> +      constexpr iterator
> +      end() noexcept
> +      { return iterator(data() + _M_size); }
> +
> +      [[nodiscard]]
> +      constexpr const_iterator
> +      end() const noexcept
> +      { return const_iterator(data() + _M_size); }
> +
> +      [[nodiscard]]
> +      constexpr reverse_iterator
> +      rbegin() noexcept
> +      { return reverse_iterator(end()); }
> +
> +      [[nodiscard]]
> +      constexpr const_reverse_iterator
> +      rbegin() const noexcept
> +      { return const_reverse_iterator(end()); }
> +
> +      [[nodiscard]]
> +      constexpr reverse_iterator
> +      rend() noexcept { return reverse_iterator(begin()); }
> +
> +      [[nodiscard]]
> +      constexpr const_reverse_iterator
> +      rend() const noexcept { return const_reverse_iterator(begin()); }
> +
> +      [[nodiscard]]
> +      constexpr const_iterator
> +      cbegin() const noexcept { return begin(); }
> +
> +      [[nodiscard]]
> +      constexpr const_iterator
> +      cend() const noexcept { return end(); }
> +
> +      [[nodiscard]]
> +      constexpr const_reverse_iterator
> +      crbegin() const noexcept { return rbegin(); }
> +
> +      [[nodiscard]]
> +      constexpr const_reverse_iterator
> +      crend() const noexcept { return rend(); }
> +
> +      // [containers.sequences.inplace.vector.members] size/capacity
> +      [[nodiscard]]
> +      constexpr bool
> +      empty() const noexcept { return _M_size == 0; }
> +
> +      [[nodiscard]]
> +      constexpr size_type
> +      size() const noexcept
> +      {
> +     if (_M_size > _Nm)
> +       __builtin_unreachable();
> +     return _M_size;
> +      }
> +
> +      [[nodiscard]]
> +      static constexpr size_type
> +      max_size() noexcept { return _Nm; }
> +
> +      [[nodiscard]]
> +      static constexpr size_type
> +      capacity() noexcept { return _Nm; }
> +
> +      constexpr void
> +      resize(size_type __n)
> +      {
> +     _S_reserve(__n);
> +     if (__n > _M_size)
> +       std::uninitialized_value_construct_n(data() + _M_size, __n - _M_size);
> +     else if (__n < _M_size)
> +       std::destroy_n(data() + __n, _M_size - __n);
> +     _M_size = __n;
> +      }
> +
> +      constexpr void
> +      resize(size_type __n, const _Tp& __c)
> +      {
> +     _S_reserve(__n);
> +     if (__n > _M_size)
> +       std::uninitialized_fill_n(data() + _M_size, __n - _M_size, __c);
> +     else if (__n < _M_size)
> +       std::destroy_n(data() + __n, _M_size - __n);
> +     _M_size = __n;
> +      }
> +
> +      static constexpr void
> +      reserve(size_type __n)
> +      { _S_reserve(__n); }
> +
> +      static constexpr void
> +      shrink_to_fit() { }
> +
> +      // element access
> +      [[nodiscard]]
> +      constexpr reference
> +      operator[](size_type __n)
> +      {
> +     __glibcxx_requires_subscript(__n);
> +     return _M_elems[__n];
> +      }
> +
> +      [[nodiscard]]
> +      constexpr const_reference
> +      operator[](size_type __n) const
> +      {
> +     __glibcxx_requires_subscript(__n);
> +     return _M_elems[__n];
> +      }
> +
> +      [[nodiscard]]
> +      constexpr const_reference
> +      at(size_type __n) const
> +      {
> +     if (__n >= _M_size)
> +       std::__throw_out_of_range_fmt(__N("inplace_vector::at: __n "
> +                                         "(which is %zu) "
> +                                         ">= size() (which is %zu)"),
> +                                     __n, _M_size);
> +     return _M_elems[__n];
> +      }
> +
> +      [[nodiscard]]
> +      constexpr reference
> +      at(size_type __n)
> +      {
> +     if (__n >= _M_size)
> +       std::__throw_out_of_range_fmt(__N("inplace_vector::at: __n "
> +                                         "(which is %zu) "
> +                                         ">= size() (which is %zu)"),
> +                                     __n, _M_size);
> +     return _M_elems[__n];
> +      }
> +
> +      [[nodiscard]]
> +      constexpr reference
> +      front()
> +      {
> +     __glibcxx_requires_nonempty();
> +     return _M_elems[0];
> +      }
> +
> +      [[nodiscard]]
> +      constexpr const_reference
> +      front() const
> +      {
> +     __glibcxx_requires_nonempty();
> +     return _M_elems[0];
> +      }
> +
> +      [[nodiscard]]
> +      constexpr reference
> +      back()
> +      {
> +     __glibcxx_requires_nonempty();
> +     return _M_elems[_M_size - 1];
> +      }
> +
> +      [[nodiscard]]
> +      constexpr const_reference
> +      back() const
> +      {
> +     __glibcxx_requires_nonempty();
> +     return _M_elems[_M_size - 1];
> +      }
> +
> +      // [containers.sequences.inplace.vector.data], data access
> +
> +      [[nodiscard]]
> +      constexpr _Tp*
> +      data() noexcept
> +      { return static_cast<pointer>(_M_elems); }
> +
> +      [[nodiscard]]
> +      constexpr const _Tp*
> +      data() const noexcept
> +      { return static_cast<const_pointer>(_M_elems); }
> +
> +      // [containers.sequences.inplace.vector.modifiers], modifiers
> +      template<typename... _Args>
> +     constexpr _Tp&
> +     emplace_back(_Args&&... __args)
> +     {
> +       if (_M_size >= _Nm)
> +         __throw_bad_alloc();
> +       return unchecked_emplace_back(std::forward<_Args>(__args)...);
> +     }
> +
> +      constexpr _Tp&
> +      push_back(const _Tp& __x)
> +      { return emplace_back(__x); }
> +
> +      constexpr _Tp&
> +      push_back(_Tp&& __x)
> +      { return emplace_back(std::move(__x)); }
> +
> +      template<__detail::__container_compatible_range<_Tp> _Rg>
> +     constexpr void
> +     append_range(_Rg&& __rg)
> +     {
> +       if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
> +         {
> +           const auto __sz = ranges::distance(__rg);
> +           if (__sz > (_Nm - size()))
> +             __throw_bad_alloc();
> +           ranges::uninitialized_copy_n(
> +             ranges::begin(__rg), __sz,
> +             data() + _M_size, unreachable_sentinel);
> +           _M_size += size_type(__sz);
> +         }
> +       else
> +         {
> +           ranges::subrange<pointer> __tail(data() + _M_size, data() + _Nm);
> +           auto [__in, __out] = ranges::uninitialized_copy(__rg, __tail);
> +           _M_size = __out - data();
> +           if (__in != ranges::end(__rg))
> +             __throw_bad_alloc();
> +         }
> +     }
> +
> +      constexpr void
> +      pop_back()
> +      {
> +     __glibcxx_requires_nonempty();
> +     --_M_size;
> +     _M_elems[_M_size].~_Tp();
> +      }
> +
> +      template<typename... _Args>
> +     constexpr _Tp*
> +     try_emplace_back(_Args&&... __args)
> +     {
> +       if (_M_size >= _Nm) [[unlikely]]
> +         return nullptr;
> +       auto& __r = unchecked_emplace_back(std::forward<_Args>(__args)...);
> +       return __builtin_addressof(__r);
> +     }
> +
> +      constexpr _Tp*
> +      try_push_back(const _Tp& __x)
> +      {
> +     if (_M_size >= _Nm) [[unlikely]]
> +       return nullptr;
> +     return __builtin_addressof(unchecked_emplace_back(__x));
> +      }
> +
> +      constexpr _Tp*
> +      try_push_back(_Tp&& __x)
> +      {
> +     if (_M_size >= _Nm) [[unlikely]]
> +       return nullptr;
> +     return __builtin_addressof(unchecked_emplace_back(std::move(__x)));
> +      }
> +
> +      template<__detail::__container_compatible_range<_Tp> _Rg>
> +     constexpr ranges::borrowed_iterator_t<_Rg>
> +     try_append_range(_Rg&& __rg)
> +     {
> +       if constexpr (ranges::sized_range<_Rg>)
> +         {
> +           auto __n = ranges::distance(__rg);
> +           if (__n == 0) [[unlikely]]
> +             return ranges::begin(__rg);
> +
> +           const auto __end = data() + _M_size;
> +           const size_t __avail = _Nm - size();
> +           if (__n <= __avail)
> +             _M_size += size_type(__n);
> +           else
> +             {
> +               __n = __avail;
> +               _M_size = _Nm;
> +             }
> +           return ranges::uninitialized_copy_n(
> +                    ranges::begin(__rg), __n,
> +                    __end, unreachable_sentinel).in;
> +         }
> +       else
> +         {
> +           ranges::subrange<pointer> __tail(data() + _M_size, data() + _Nm);
> +           auto [__in, __out] = ranges::uninitialized_copy(__rg, __tail);
> +           _M_size = __out - data();
> +           return std::move(__in);
> +         }
> +     }
> +
> +      template<typename... _Args>
> +     constexpr _Tp&
> +     unchecked_emplace_back(_Args&&... __args)
> +     {
> +       __glibcxx_assert(_M_size < _Nm);
> +       auto __p = std::construct_at(data() + _M_size,
> +                                    std::forward<_Args>(__args)...);
> +       ++_M_size;
> +       return *__p;
> +     }
> +
> +      constexpr _Tp&
> +      unchecked_push_back(const _Tp& __x)
> +      { return unchecked_emplace_back(__x); }
> +
> +      constexpr _Tp&
> +      unchecked_push_back(_Tp&& __x)
> +      { return unchecked_emplace_back(std::move(__x)); }
> +
> +      template<typename... _Args>
> +     constexpr iterator
> +     emplace(const_iterator __position, _Args&&... __args)
> +     {
> +       size_t __b = __position - cbegin(); // elements before position
> +       __glibcxx_assert(__b <= _M_size);
> +       if (_M_size >= _Nm)
> +         __throw_bad_alloc();
> +       iterator __pos = begin() + __b;
> +       std::construct_at(data() + _M_size, std::forward<_Args>(__args)...);
> +       if (_M_size++)
> +         std::rotate(__pos, end() - 1, end());
> +       return __pos;
> +     }
> +
> +      constexpr iterator
> +      insert(const_iterator __position, const _Tp& __x)
> +      { return emplace(__position, __x); }
> +
> +      constexpr iterator
> +      insert(const_iterator __position, _Tp&& __x)
> +      { return emplace(__position, std::move(__x)); }
> +
> +      constexpr iterator
> +      insert(const_iterator __position, size_type __n, const _Tp& __x)
> +      {
> +     size_t __b = __position - cbegin(); // elements before position
> +     __glibcxx_assert(__b <= _M_size);
> +     if ((_Nm - _M_size) < __n)
> +       __throw_bad_alloc();
> +     iterator __pos = begin() + __b;
> +     std::uninitialized_fill_n(data() + _M_size, __n, __x);
> +     if (std::__exchange(_M_size, _M_size + __n))
> +       std::rotate(__pos, end() - __n, end());
> +     return __pos;
> +      }
> +
> +      template<__any_input_iterator _InputIterator>
> +     constexpr iterator
> +     insert(const_iterator __position, _InputIterator __first,
> +            _InputIterator __last)
> +     {
> +       size_t __b = __position - cbegin(); // elements before position
> +       __glibcxx_assert(__b <= _M_size);
> +       iterator __pos = begin() + __b;
> +       const size_t __s = _M_size;
> +       if (const auto __n = _S_distance(__first, __last))
> +         {
> +           if ((_Nm - _M_size) < __n)
> +             __throw_bad_alloc();
> +           std::uninitialized_copy(__first, __last, data() + _M_size);
> +           _M_size += __n;
> +         }
> +       else
> +         {
> +           while (__first != __last)
> +             emplace_back(*__first++);
> +         }
> +       if (__s)
> +         std::rotate(__pos, begin() + __s, end());
> +       return __pos;
> +     }
> +
> +      template<__detail::__container_compatible_range<_Tp> _Rg>
> +     constexpr iterator
> +     insert_range(const_iterator __position, _Rg&& __rg)
> +     {
> +       iterator __pos = begin() + (__position - cbegin());
> +       const auto __end = end();
> +       if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
> +         {
> +           const auto __len = ranges::distance(__rg);
> +           if (__len > (_Nm - size()))
> +             __throw_bad_alloc();
> +           if (!__len) [[unlikely]]
> +             return __pos;
> +
> +           const size_type __n = size_type(__len);
> +           const size_type __num_after = __end - __pos;
> +           if (__num_after >= __n)
> +             {
> +               ranges::uninitialized_move(__end - __n, __end,
> +                                          __end, unreachable_sentinel);
> +               _M_size += __n;
> +               ranges::move_backward(__pos, __end - __n, __end);
> +               ranges::copy(__rg, __pos);
> +             }
> +           else if constexpr (ranges::forward_range<_Rg>)
> +             {
> +               auto __mid = ranges::next(ranges::begin(__rg), __num_after);
> +               ranges::uninitialized_copy(__mid, ranges::end(__rg),
> +                                          __end, unreachable_sentinel);
> +               _M_size += __n - __num_after;
> +               ranges::uninitialized_move(__pos, __end,
> +                                          __pos + __n, unreachable_sentinel);
> +               _M_size += __num_after;
> +               ranges::copy(ranges::begin(__rg), __mid, __pos);
> +             }
> +           else
> +             {
> +               ranges::uninitialized_copy(
> +                 ranges::begin(__rg), ranges::end(__rg),
> +                 __end, unreachable_sentinel);
> +               _M_size += __n;
> +               std::rotate(__pos, __end, end());
> +             }
> +         }
> +       else
> +         {
> +           append_range(__rg);
> +           std::rotate(__pos, __end, end());
> +         }
> +       return __pos;
> +     }
> +
> +      constexpr iterator
> +      insert(const_iterator __position, initializer_list<_Tp> __il)
> +      { return insert(__position, __il.begin(), __il.end()); }
> +
> +      constexpr iterator
> +      erase(const_iterator __position)
> +      {
> +     size_t __n = __position - cbegin();
> +     __glibcxx_assert(__n < _M_size);
> +     iterator __pos = begin() + __n;
> +     std::move(__pos + 1, end(), __pos);
> +     pop_back();
> +     return __pos;
> +      }
> +
> +      constexpr iterator
> +      erase(const_iterator __first, const_iterator __last)
> +      {
> +     size_t __n = __first - cbegin();
> +     size_t __x = __last - __first;
> +     __glibcxx_assert(__n <= _M_size);
> +     __glibcxx_assert(__x <= _M_size);
> +     iterator __pos = begin() + __n;
> +     iterator __end = std::move(__pos + __x, end(), __pos);
> +     std::destroy_n(__end, __x);
> +     _M_size -= __x;
> +     return __pos;
> +      }
> +
> +      constexpr void
> +      swap(inplace_vector& __x)
> +      noexcept(is_nothrow_swappable_v<_Tp> && 
> is_nothrow_move_constructible_v<_Tp>)
> +      {
> +     inplace_vector* __vs[2]{ this, std::addressof(__x) };
> +     const auto __smaller = __vs[__x.size() < size()];
> +     const auto __bigger = __vs[__x.size() >= size()];
> +     size_type __n = __smaller->size();
> +     size_type __n2 = __bigger->size();
> +
> +     if constexpr (is_nothrow_move_constructible_v<_Tp>)
> +       {
> +         for (size_type __i = __n; __i < __n2; ++__i)
> +           {
> +             std::construct_at(__smaller->data() + __i,
> +                               std::move(*(__bigger->data() + __i)));
> +             std::destroy_at(__bigger->data() + __i);
> +           }
> +       }
> +     else
> +       {
> +         std::uninitialized_copy(__bigger->data() + __n,
> +                                 __bigger->data() + __n2,
> +                                 __smaller->data() + __n);
> +         std::destroy(__bigger->data() + __n, __bigger->data() + __n2);
> +       }
> +     __smaller->_M_size = __n2;
> +     __bigger->_M_size = __n;
> +
> +     using std::swap;
> +     for (size_type __i = 0; __i < __n; __i++)
> +       swap(_M_elems[__i], __x._M_elems[__i]);
> +      }
> +
> +      constexpr void
> +      clear() noexcept
> +      {
> +     std::destroy_n(data(), size_t(_M_size));
> +     _M_size = 0;
> +      }
> +
> +      constexpr friend bool
> +      operator==(const inplace_vector& __x, const inplace_vector& __y)
> +      { return std::equal(__x.begin(), __x.end(), __y.begin(), __y.end()); }
> +
> +      constexpr friend auto
> +      operator<=>(const inplace_vector& __x, const inplace_vector& __y)
> +      requires requires (const _Tp __t) {
> +     { __t < __t } -> __detail::__boolean_testable;
> +      }
> +      {
> +     return std::lexicographical_compare_three_way(__x.begin(), __x.end(),
> +                                                   __y.begin(), __y.end(),
> +                                                   __detail::__synth3way);
> +      }
> +
> +      constexpr friend void
> +      swap(inplace_vector& __x, inplace_vector& __y)
> +      noexcept(is_nothrow_swappable_v<_Tp> && 
> is_nothrow_move_constructible_v<_Tp>)
> +      { __x.swap(__y); }
> +
> +    private:
> +      union {
> +     _Tp _M_elems[_Nm];
> +      };
> +
> +      // Check whether integer type _UInt is wide enough to store _Nm,
> +      // so that we use a smaller type for _M_size when that saves space.
> +      template<typename _UInt, bool = (alignof(_Tp) <= sizeof(_UInt))>
> +     static constexpr bool __fits
> +       = _Nm <= __gnu_cxx::__int_traits<_UInt>::__max;
> +
> +      // Don't bother using a smaller type if alignment of the array elements
> +      // means that it doesn't actually save space.
> +      template<typename _UInt>
> +     static constexpr bool __fits<_UInt, false> = false;
> +
> +      static consteval auto __select_size_type()
> +      {
> +     if constexpr (__fits<unsigned char>)
> +       return (unsigned char)0;
> +#if __SHRT_WIDTH__ < __SIZE_WIDTH__
> +     else if constexpr (__fits<unsigned short>)
> +       return (unsigned short)0;
> +#endif
> +#if __INT_WIDTH__ < __SIZE_WIDTH__ && __INT_WIDTH__ > __SHRT_WIDTH__
> +     else if constexpr (__fits<unsigned int>)
> +       return 0u;
> +#endif
> +#if __LONG_WIDTH__ < __SIZE_WIDTH__ && __LONG_WIDTH__ > __INT_WIDTH__
> +     else if constexpr (__fits<unsigned long>)
> +       return 0ul;
> +#endif
> +     else // Just use size_t.
> +       return 0uz;
> +      }
> +      decltype(__select_size_type()) _M_size = 0;
> +
> +      constexpr void
> +      _M_init()
> +      {
> +     if !consteval
> +       {
> +#if __glibcxx_start_lifetime_as
> +         std::start_lifetime_as_array<_Tp>(data(), _Nm);
> +#endif
> +       }
> +     else
> +       {
> +         // TODO: use new(_M_elems) _Tp[_Nm]() once PR121068 is fixed
> +         if constexpr (is_trivial_v<_Tp>)
> +           for (size_t __i = 0; __i < _Nm; ++__i)
> +             _M_elems[__i] = _Tp();
> +         else
> +           __builtin_unreachable(); // only trivial types are supported at 
> compile time
> +       }
> +      }
> +
> +      static constexpr void
> +      _S_reserve(size_t __n)
> +      {
> +     if (__n > _Nm)
> +       __throw_bad_alloc();
> +      }
> +
> +      template<typename _InputIterator>
> +     constexpr static auto
> +     _S_distance(_InputIterator __first, _InputIterator __last)
> +     {
> +       if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>
> +                       || forward_iterator<_InputIterator>)
> +         return (size_type)ranges::distance(__first, __last);
> +       else if constexpr (derived_from<__iter_category_t<_InputIterator>,
> +                                  forward_iterator_tag>)
> +         return (size_type)std::distance(__first, __last);
> +       else
> +         return false_type{};
> +     }
> +    };
> +
> +  // [inplace.vector.special], specialized algorithms
> +  template<typename _Tp, size_t _Nm>
> +    constexpr void
> +    swap(inplace_vector<_Tp, _Nm>& __x, inplace_vector<_Tp, _Nm>& __y)
> +    noexcept(noexcept(__x.swap(__y)))
> +    { __x.swap(__y); }
> +
> +  // specialization for zero capacity, that is required to be trivally 
> copyable
> +  // and empty regardless of _Tp.
> +  template<typename _Tp>
> +    class inplace_vector<_Tp, 0>
> +    {
> +    public:
> +      // types:
> +      using value_type             = _Tp;
> +      using pointer                = _Tp*;
> +      using const_pointer          = const _Tp*;
> +      using reference              = value_type&;
> +      using const_reference        = const value_type&;
> +      using size_type              = size_t;
> +      using difference_type        = ptrdiff_t;
> +      using iterator
> +     = __gnu_cxx::__normal_iterator<_Tp*, inplace_vector>;
> +      using const_iterator
> +     = __gnu_cxx::__normal_iterator<const _Tp*, inplace_vector>;
> +      using reverse_iterator       = std::reverse_iterator<iterator>;
> +      using const_reverse_iterator = std::reverse_iterator<const_iterator>;
> +
> +      // [containers.sequences.inplace.vector.cons], construct/copy/destroy
> +      inplace_vector() = default;
> +
> +      constexpr explicit
> +      inplace_vector(size_type __n)
> +      {
> +     if (__n != 0)
> +       __throw_bad_alloc();
> +      }
> +
> +      constexpr
> +      inplace_vector(size_type __n, const _Tp& __value)
> +      {
> +     if (__n != 0)
> +       __throw_bad_alloc();
> +      }
> +
> +      template<__any_input_iterator _InputIterator>
> +     constexpr
> +     inplace_vector(_InputIterator __first, _InputIterator __last)
> +     {
> +       if (__first != __last)
> +         __throw_bad_alloc();
> +     }
> +
> +      template <__detail::__container_compatible_range<_Tp> _Rg>
> +     constexpr
> +     inplace_vector(from_range_t, _Rg&& __rg)
> +     {
> +       if (ranges::begin(__rg) != ranges::end(__rg))
> +         __throw_bad_alloc();
> +     }
> +
> +      constexpr
> +      inplace_vector(initializer_list<_Tp> __il)
> +      {
> +     if (__il.size() != 0)
> +       __throw_bad_alloc();
> +      }
> +
> +      inplace_vector(const inplace_vector&) = default;
> +      inplace_vector(inplace_vector&&) = default;
> +
> +      constexpr
> +      ~inplace_vector() = default;
> +
> +      inplace_vector&
> +      operator=(const inplace_vector&) = default;
> +
> +      inplace_vector&
> +      operator=(inplace_vector&&) = default;
> +
> +      constexpr inplace_vector&
> +      operator=(initializer_list<_Tp> __il)
> +      {
> +     if (__il.size() != 0)
> +       __throw_bad_alloc();
> +      }
> +
> +      template<__any_input_iterator _InputIterator>
> +     constexpr void
> +     assign(_InputIterator __first, _InputIterator __last)
> +     {
> +       if (__first != __last)
> +         __throw_bad_alloc();
> +     }
> +
> +      template<__detail::__container_compatible_range<_Tp> _Rg>
> +     constexpr void
> +     assign_range(_Rg&& __rg)
> +     {
> +       if (ranges::begin(__rg) != ranges::end(__rg))
> +         __throw_bad_alloc();
> +     }
> +
> +      constexpr void
> +      assign(size_type __n, const _Tp& __u)
> +      {
> +     if (__n != 0)
> +       __throw_bad_alloc();
> +      }
> +
> +      constexpr void
> +      assign(initializer_list<_Tp> __il)
> +      {
> +     if (__il.size() != 0)
> +       __throw_bad_alloc();
> +      }
> +
> +      // iterators
> +      [[nodiscard]]
> +      constexpr iterator
> +      begin() noexcept { return iterator(nullptr); }
> +
> +      [[nodiscard]]
> +      constexpr const_iterator
> +      begin() const noexcept { return const_iterator(nullptr); }
> +
> +      [[nodiscard]]
> +      constexpr iterator
> +      end() noexcept { return iterator(nullptr); }
> +
> +      [[nodiscard]]
> +      constexpr const_iterator
> +      end() const noexcept { return const_iterator(nullptr); }
> +
> +      [[nodiscard]]
> +      constexpr reverse_iterator
> +      rbegin() noexcept
> +      { return reverse_iterator(end()); }
> +
> +      [[nodiscard]]
> +      constexpr const_reverse_iterator
> +      rbegin() const noexcept
> +      { return const_reverse_iterator(end()); }
> +
> +      [[nodiscard]]
> +      constexpr reverse_iterator
> +      rend() noexcept { return reverse_iterator(begin()); }
> +
> +      [[nodiscard]]
> +      constexpr const_reverse_iterator
> +      rend() const noexcept { return const_reverse_iterator(begin()); }
> +
> +      [[nodiscard]]
> +      constexpr const_iterator
> +      cbegin() const noexcept { return begin(); }
> +
> +      [[nodiscard]]
> +      constexpr const_iterator
> +      cend() const noexcept { return end(); }
> +
> +      [[nodiscard]]
> +      constexpr const_reverse_iterator
> +      crbegin() const noexcept { return rbegin(); }
> +
> +      [[nodiscard]]
> +      constexpr const_reverse_iterator
> +      crend() const noexcept { return rend(); }
> +
> +      // [containers.sequences.inplace.vector.members] size/capacity
> +      [[nodiscard]]
> +      constexpr bool
> +      empty() const noexcept { return true; }
> +
> +      [[nodiscard]]
> +      constexpr size_type
> +      size() const noexcept { return 0; }
> +
> +      [[nodiscard]]
> +      static constexpr size_type
> +      max_size() noexcept { return 0; }
> +
> +      [[nodiscard]]
> +      static constexpr size_type
> +      capacity() noexcept { return 0; }
> +
> +      constexpr void
> +      resize(size_type __n)
> +      {
> +     if (__n != 0)
> +       __throw_bad_alloc();
> +      }
> +
> +      constexpr void
> +      resize(size_type __n, const _Tp&)
> +      {
> +     if (__n != 0)
> +       __throw_bad_alloc();
> +      }
> +
> +      static constexpr void
> +      reserve(size_type __n)
> +      {
> +     if (__n != 0)
> +       __throw_bad_alloc();
> +      }
> +
> +      static constexpr void
> +      shrink_to_fit() { }
> +
> +      // element access
> +      [[nodiscard,noreturn]]
> +      constexpr reference
> +      operator[](size_type)
> +      { __builtin_trap(); }
> +
> +      [[nodiscard,noreturn]]
> +      constexpr const_reference
> +      operator[](size_type) const
> +      { __builtin_trap(); }
> +
> +      [[nodiscard,noreturn]]
> +      constexpr const_reference
> +      at(size_type __n) const
> +      {
> +     std::__throw_out_of_range_fmt(__N("inplace_vector::at: __n "
> +                                       "(which is %zu) "
> +                                       ">= size() (which is 0)"),
> +                                   __n);
> +      }
> +
> +      [[nodiscard,noreturn]]
> +      constexpr reference
> +      at(size_type __n)
> +      {
> +     std::__throw_out_of_range_fmt(__N("inplace_vector::at: __n "
> +                                       "(which is %zu) "
> +                                       ">= size() (which is 0)"),
> +                                   __n);
> +      }
> +
> +      [[nodiscard,noreturn]]
> +      constexpr reference
> +      front()
> +      { __builtin_trap(); }
> +
> +      [[nodiscard,noreturn]]
> +      constexpr const_reference
> +      front() const
> +      { __builtin_trap(); }
> +
> +      [[nodiscard,noreturn]]
> +      constexpr reference
> +      back()
> +      { __builtin_trap(); }
> +
> +      [[nodiscard,noreturn]]
> +      constexpr const_reference
> +      back() const
> +      { __builtin_trap(); }
> +
> +      // [containers.sequences.inplace.vector.data], data access
> +
> +      [[nodiscard]]
> +      constexpr _Tp*
> +      data() noexcept
> +      { return nullptr; }
> +
> +      [[nodiscard]]
> +      constexpr const _Tp*
> +      data() const noexcept
> +      { return nullptr; }
> +
> +      // [containers.sequences.inplace.vector.modifiers], modifiers
> +      template<typename... _Args>
> +     [[noreturn]]
> +     constexpr _Tp&
> +     emplace_back(_Args&&...)
> +     { __throw_bad_alloc(); }
> +
> +      [[noreturn]]
> +      constexpr _Tp&
> +      push_back(const _Tp&)
> +      { __throw_bad_alloc(); }
> +
> +      [[noreturn]]
> +      constexpr _Tp&
> +      push_back(_Tp&&)
> +      { __throw_bad_alloc(); }
> +
> +      template<__detail::__container_compatible_range<_Tp> _Rg>
> +     constexpr void
> +     append_range(_Rg&& __rg)
> +     {
> +       if (ranges::begin(__rg) != ranges::end(__rg))
> +         __throw_bad_alloc();
> +     }
> +
> +      [[noreturn]]
> +      constexpr void
> +      pop_back()
> +      { __builtin_trap(); }
> +
> +      template<typename... _Args>
> +     constexpr _Tp*
> +     try_emplace_back(_Args&&...)
> +     { return nullptr; }
> +
> +      constexpr _Tp*
> +      try_push_back(const _Tp&)
> +      { return nullptr; }
> +
> +      constexpr _Tp*
> +      try_push_back(_Tp&&)
> +      { return nullptr; }
> +
> +      template<__detail::__container_compatible_range<_Tp> _Rg>
> +     constexpr ranges::borrowed_iterator_t<_Rg>
> +     try_append_range(_Rg&& __rg)
> +     { return ranges::begin(__rg); }
> +
> +      template<typename... _Args>
> +     [[noreturn]]
> +     constexpr _Tp&
> +     unchecked_emplace_back(_Args&&...)
> +     { __builtin_trap(); }
> +
> +      [[noreturn]]
> +      constexpr _Tp&
> +      unchecked_push_back(const _Tp&)
> +      { __builtin_trap(); }
> +
> +      [[noreturn]]
> +      constexpr _Tp&
> +      unchecked_push_back(_Tp&&)
> +      { __builtin_trap(); }
> +
> +      template<typename... _Args>
> +     [[noreturn]]
> +     constexpr iterator
> +     emplace(const_iterator, _Args&&...)
> +     { __throw_bad_alloc(); }
> +
> +      [[noreturn]]
> +      constexpr iterator
> +      insert(const_iterator, const _Tp&)
> +      { __throw_bad_alloc(); }
> +
> +      [[noreturn]]
> +      constexpr iterator
> +      insert(const_iterator, _Tp&&)
> +      { __throw_bad_alloc(); }
> +
> +      constexpr iterator
> +      insert(const_iterator, size_type __n, const _Tp&)
> +      {
> +     if (__n != 0)
> +       __throw_bad_alloc();
> +     return begin();
> +      }
> +
> +      template<typename _InputIterator>
> +     constexpr iterator
> +     insert(const_iterator, _InputIterator __first, _InputIterator __last)
> +     {
> +       if (__first != __last)
> +         __throw_bad_alloc();
> +       return begin();
> +     }
> +
> +      template<__detail::__container_compatible_range<_Tp> _Rg>
> +     constexpr iterator
> +     insert_range(const_iterator, _Rg&& __rg)
> +     {
> +       if (ranges::begin(__rg) != ranges::end(__rg))
> +         __throw_bad_alloc();
> +       return begin();
> +     }
> +
> +      constexpr iterator
> +      insert(const_iterator, initializer_list<_Tp> __il)
> +      {
> +     if (__il.size() != 0)
> +       __throw_bad_alloc();
> +     return begin();
> +      }
> +
> +      [[noreturn]]
> +      constexpr iterator
> +      erase(const_iterator)
> +      { __builtin_trap(); }
> +
> +      constexpr iterator
> +      erase(const_iterator __first, const_iterator __last)
> +      {
> +     __glibcxx_assert(__first == __last);
> +     return begin();
> +      }
> +
> +      constexpr void
> +      swap(inplace_vector& __x)
> +      noexcept
> +      { }
> +
> +      constexpr void
> +      clear() noexcept
> +      { }
> +
> +      constexpr friend bool
> +      operator==(const inplace_vector&, const inplace_vector&)
> +      { return true; }
> +
> +      constexpr friend auto
> +      operator<=>(const inplace_vector&, const inplace_vector&)
> +      requires requires (const _Tp __t) {
> +     { __t < __t } -> __detail::__boolean_testable;
> +      }
> +      {      return std::strong_ordering::equal; }
> +
> +      // n.b. there is not explicit wording requiring that swap for 
> inplace_vector,
> +      // with zero size, works even if element type is not swappable. 
> However given
> +      // that move operations are required to be present and trivial, it 
> makes sense
> +      // to support them.
> +      constexpr friend void
> +      swap(inplace_vector&, inplace_vector&) noexcept
> +      { }
> +    };
> +
> +  template<typename _Tp, size_t _Nm, typename _Predicate>
> +    constexpr size_t
> +    erase_if(inplace_vector<_Tp, _Nm>& __cont, _Predicate __pred)
> +    {
> +      using namespace __gnu_cxx;
> +      const auto __osz = __cont.size();
> +      const auto __end = __cont.end();
> +      auto __removed = std::__remove_if(__cont.begin(), __end,
> +                                     __ops::__pred_iter(std::ref(__pred)));
> +      if (__removed != __end)
> +     {
> +       __cont.erase(__niter_wrap(__cont.begin(), __removed),
> +                    __cont.end());
> +       return __osz - __cont.size();
> +     }
> +      return 0;
> +    }
> +
> +
> +  template<typename _Tp, size_t _Nm, typename _Up>
> +    constexpr  size_t
> +    erase(inplace_vector<_Tp, _Nm>& __cont, const _Up& __value)
> +    {
> +      using namespace __gnu_cxx;
> +      const auto __osz = __cont.size();
> +      const auto __end = __cont.end();
> +      auto __removed = std::__remove_if(__cont.begin(), __end,
> +                                     __ops::__iter_equals_val(__value));
> +      if (__removed != __end)
> +     {
> +       __cont.erase(__niter_wrap(__cont.begin(), __removed),
> +                    __cont.end());
> +       return __osz - __cont.size();
> +     }
> +      return 0;
> +    }
> +
> +_GLIBCXX_END_NAMESPACE_VERSION
> +} // namespace
> +
> +#endif // __glibcxx_inplace_vector
> +#endif // _GLIBCXX_INPLACE_VECTOR
> diff --git a/libstdc++-v3/src/c++23/std.cc.in 
> b/libstdc++-v3/src/c++23/std.cc.in
> index dd05a839a92..1bd4bd58f21 100644
> --- a/libstdc++-v3/src/c++23/std.cc.in
> +++ b/libstdc++-v3/src/c++23/std.cc.in
> @@ -1513,7 +1513,15 @@ export namespace std
>    using std::initializer_list;
>  }
>  
> -// <inplace_vector> FIXME
> +// <inplace_vector>
> +#if __cpp_lib_inplace_vector
> +export namespace std
> +{
> +  using std::inplace_vector;
> +  using std::erase;
> +  using std::erase_if;
> +}
> +#endif
>  
>  // <iomanip>
>  export namespace std
> diff --git 
> a/libstdc++-v3/testsuite/23_containers/inplace_vector/access/capacity.cc 
> b/libstdc++-v3/testsuite/23_containers/inplace_vector/access/capacity.cc
> new file mode 100644
> index 00000000000..2797e205971
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/access/capacity.cc
> @@ -0,0 +1,51 @@
> +// { dg-do run { target c++26 } }
> +
> +#include <inplace_vector>
> +
> +#include <span>
> +#include <testsuite_hooks.h>
> +
> +template<size_t N, typename T>
> +constexpr void
> +test_reserve()
> +{
> +  std::inplace_vector<T, N> v;
> +
> +  static_assert(v.max_size() == N);
> +  static_assert(v.capacity() == N);
> +
> +  // static methods
> +  v.shrink_to_fit();
> +  v.reserve(0);
> +  v.reserve(N);
> +
> +#ifdef __cpp_exceptions
> +#ifdef __cpp_lib_constexpr_exceptions
> +#error remove the consteval check
> +#endif
> +  if consteval {
> +    return;
> +  }
> +
> +  try
> +  {
> +    v.reserve(N + 2);
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +#endif
> +}
> +
> +int main()
> +{
> +  auto test_all = [] {
> +    test_reserve<0, int>();
> +    test_reserve<4, int>();
> +    return true;
> +  };
> +
> +  test_all();
> +  static_assert(test_all());;
> +}
> diff --git 
> a/libstdc++-v3/testsuite/23_containers/inplace_vector/access/elem.cc 
> b/libstdc++-v3/testsuite/23_containers/inplace_vector/access/elem.cc
> new file mode 100644
> index 00000000000..a598514bd9b
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/access/elem.cc
> @@ -0,0 +1,103 @@
> +// { dg-do run { target c++26 } }
> +
> +#include <inplace_vector>
> +
> +#include <span>
> +#include <stdexcept>
> +#include <testsuite_hooks.h>
> +#include <utility>
> +
> +template<size_t N, typename T>
> +constexpr void
> +test_out_of_capacity()
> +{
> +  std::inplace_vector<T, N> v;
> +
> +#ifdef __cpp_exceptions
> +#ifdef __cpp_lib_constexpr_exceptions
> +#error remove the consteval check
> +#endif
> +  if consteval {
> +    return;
> +  }
> +
> +  try
> +  {
> +    (void)v.at(N + 2);
> +    VERIFY(false);
> +  }
> +  catch (std::out_of_range const&)
> +  {
> +  }
> +
> +  try
> +  {
> +    (void)as_const(v).at(N + 2);
> +    VERIFY(false);
> +  }
> +  catch (std::out_of_range const&)
> +  {
> +  }
> +#endif
> +}
> +
> +template<typename T>
> +constexpr void
> +test_access()
> +{
> +  std::inplace_vector<T, 10> v{1, 2, 3, 4, 5};
> +
> +  auto& e3a = v[2];
> +  auto& e3b = std::as_const(v).at(2);
> +  VERIFY( &e3a == &e3b );
> +  VERIFY( &e3a == &v.begin()[2] );
> +  VERIFY( &e3a == std::as_const(v).data() + 2 );
> +  VERIFY( e3a == T(3) );
> +
> +  auto& e4a = as_const(v)[4];
> +  auto& e4b = v.at(4);
> +  VERIFY( &e4a == &e4b );
> +  VERIFY( &e4a == &v.cbegin()[4] );
> +  VERIFY( &e4a == v.data() + 4 );
> +  VERIFY( e4a == T(5) );
> +
> +#ifdef __cpp_exceptions
> +#ifdef __cpp_lib_constexpr_exceptions
> +#error remove the consteval check
> +#endif
> +  if consteval {
> +    return;
> +  }
> +
> +  try
> +  {
> +    (void)v.at(7);
> +    VERIFY(false);
> +  }
> +  catch (std::out_of_range const&)
> +  {
> +  }
> +
> +  try
> +  {
> +    (void)as_const(v).at(7);
> +    VERIFY(false);
> +  }
> +  catch (std::out_of_range const&)
> +  {
> +  }
> +#endif
> +}
> +
> +int main()
> +{
> +  auto test_all = [] {
> +    test_out_of_capacity<0, int>();
> +    test_out_of_capacity<4, int>();
> +    test_access<int>();
> +    return true;
> +  };
> +
> +  test_all();
> +  static_assert(test_all());;
> +}
> diff --git 
> a/libstdc++-v3/testsuite/23_containers/inplace_vector/access/elem_neg.cc 
> b/libstdc++-v3/testsuite/23_containers/inplace_vector/access/elem_neg.cc
> new file mode 100644
> index 00000000000..e3ba5eb6866
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/access/elem_neg.cc
> @@ -0,0 +1,29 @@
> +// { dg-do compile { target c++26 } }
> +
> +#include <inplace_vector>
> +
> +template<size_t N, typename T>
> +constexpr bool
> +test_out_of_capacity()
> +{
> +  std::inplace_vector<T, N> v;
> +  (void)v[N+2]; // { dg-error "in 'constexpr' expansion of" }
> +  return true;
> +}
> +
> +template<typename T>
> +constexpr bool
> +test_out_of_size()
> +{
> +  std::inplace_vector<T, 10> v{1, 2, 3, 4, 5};
> +  (void)v[7]; // { dg-error "in 'constexpr' expansion of" }
> +  return true;
> +}
> +
> +static_assert(test_out_of_capacity<0, int>()); // { dg-error "in 'constexpr' 
> expansion of" }
> +static_assert(test_out_of_capacity<4, int>()); // { dg-error "in 'constexpr' 
> expansion of" }
> +static_assert(test_out_of_size<int>());        // { dg-error "in 'constexpr' 
> expansion of" }
> +
> +// { dg-prune-output "non-constant condition for static assertion" }
> +// { dg-prune-output "is not a constant expression" }
> +// { dg-prune-output "call to non-'constexpr' function" }
> diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/cons/1.cc 
> b/libstdc++-v3/testsuite/23_containers/inplace_vector/cons/1.cc
> new file mode 100644
> index 00000000000..e9c2cdc8665
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/cons/1.cc
> @@ -0,0 +1,385 @@
> +// { dg-do run { target c++26 } }
> +
> +#include <inplace_vector>
> +#include <testsuite_hooks.h>
> +
> +struct X
> +{
> +  constexpr X() { } // not trivially default constructible
> +};
> +
> +struct N
> +{
> +  constexpr N() noexcept { } // not trivially default constructible
> +};
> +
> +struct D
> +{
> +  ~D() {} // not trivially destructible
> +};
> +
> +struct U
> +{
> +  U() noexcept(false) = default; // lies about noexcept
> +};
> +
> +// n5008 inplace.vector.overview says for inplace_vector<T, 0>
> +// provides trivial copy/move/default cosntructpr regardless of T
> +struct Z
> +{
> +  constexpr Z(int) {}
> +  Z() = delete;
> +};
> +
> +static_assert(std::is_default_constructible_v<std::inplace_vector<int, 2>>);
> +static_assert(std::is_default_constructible_v<std::inplace_vector<X, 2>>);
> +static_assert(std::is_default_constructible_v<std::inplace_vector<N, 2>>);
> +static_assert(std::is_default_constructible_v<std::inplace_vector<D, 2>>);
> +static_assert(std::is_default_constructible_v<std::inplace_vector<U, 2>>);
> +// The operators are not constrained, as for any other container
> +static_assert(std::is_default_constructible_v<std::inplace_vector<Z, 2>>);
> +
> +static_assert(std::is_nothrow_default_constructible_v<std::inplace_vector<int,
>  2>>);
> +static_assert(std::is_nothrow_default_constructible_v<std::inplace_vector<X, 
> 2>>);
> +static_assert(std::is_nothrow_default_constructible_v<std::inplace_vector<N, 
> 2>>);
> +static_assert(std::is_nothrow_default_constructible_v<std::inplace_vector<D, 
> 2>>);
> +static_assert(std::is_nothrow_default_constructible_v<std::inplace_vector<U, 
> 2>>);
> +
> +// Needs to set size to zero, not trivial
> +static_assert(!std::is_trivially_default_constructible_v<std::inplace_vector<int,
>  2>>);
> +static_assert(!std::is_trivially_default_constructible_v<std::inplace_vector<X,
>  2>>);
> +static_assert(!std::is_trivially_default_constructible_v<std::inplace_vector<N,
>  2>>);
> +static_assert(!std::is_trivially_default_constructible_v<std::inplace_vector<D,
>  2>>);
> +static_assert(!std::is_trivially_default_constructible_v<std::inplace_vector<U,
>  2>>);
> +
> +static_assert(std::is_trivially_destructible_v<std::inplace_vector<int, 2>>);
> +static_assert(std::is_trivially_destructible_v<std::inplace_vector<X, 2>>);
> +static_assert(std::is_trivially_destructible_v<std::inplace_vector<N, 2>>);
> +static_assert(!std::is_trivially_destructible_v<std::inplace_vector<D, 2>>);
> +static_assert(std::is_trivially_destructible_v<std::inplace_vector<U, 2>>);
> +
> +static_assert(std::is_nothrow_default_constructible_v<std::inplace_vector<int,
>  0>>);
> +static_assert(std::is_nothrow_default_constructible_v<std::inplace_vector<X, 
> 0>>);
> +static_assert(std::is_nothrow_default_constructible_v<std::inplace_vector<N, 
> 0>>);
> +static_assert(std::is_nothrow_default_constructible_v<std::inplace_vector<D, 
> 0>>);
> +static_assert(std::is_nothrow_default_constructible_v<std::inplace_vector<U, 
> 0>>);
> +
> +// Size is always zero, so trivial
> +static_assert(std::is_trivially_default_constructible_v<std::inplace_vector<int,
>  0>>);
> +static_assert(std::is_trivially_default_constructible_v<std::inplace_vector<X,
>  0>>);
> +static_assert(std::is_trivially_default_constructible_v<std::inplace_vector<N,
>  0>>);
> +static_assert(std::is_trivially_default_constructible_v<std::inplace_vector<D,
>  0>>);
> +static_assert(std::is_trivially_default_constructible_v<std::inplace_vector<U,
>  0>>);
> +static_assert(std::is_trivially_default_constructible_v<std::inplace_vector<Z,
>  0>>);
> +
> +static_assert(std::is_trivially_destructible_v<std::inplace_vector<int, 0>>);
> +static_assert(std::is_trivially_destructible_v<std::inplace_vector<X, 0>>);
> +static_assert(std::is_trivially_destructible_v<std::inplace_vector<N, 0>>);
> +static_assert(std::is_trivially_destructible_v<std::inplace_vector<D, 0>>);
> +static_assert(std::is_trivially_destructible_v<std::inplace_vector<U, 0>>);
> +
> +static_assert(std::is_empty_v<std::inplace_vector<int, 0>>);
> +static_assert(std::is_empty_v<std::inplace_vector<X, 0>>);
> +static_assert(std::is_empty_v<std::inplace_vector<N, 0>>);
> +static_assert(std::is_empty_v<std::inplace_vector<D, 0>>);
> +static_assert(std::is_empty_v<std::inplace_vector<U, 0>>);
> +static_assert(std::is_empty_v<std::inplace_vector<Z, 0>>);
> +
> +constexpr void
> +test_default()
> +{
> +  std::inplace_vector<int, 5> c;
> +  VERIFY( c.size() == 0 );
> +  VERIFY( c.capacity() == 5 );
> +  VERIFY( c.empty() );
> +  VERIFY( c.begin() == c.end() );
> +
> +  std::inplace_vector<int, 0> c0;
> +  VERIFY( c0.size() == 0 );
> +  VERIFY( c0.capacity() == 0 );
> +  VERIFY( c0.empty() );
> +  VERIFY( c0.begin() == c0.end() );
> +
> +  std::inplace_vector<Z, 0> z0;
> +  VERIFY( z0.size() == 0 );
> +  VERIFY( z0.capacity() == 0 );
> +  VERIFY( z0.empty() );
> +  VERIFY( z0.begin() == z0.end() );
> +
> +#ifdef __cpp_lib_constexpr_inplace_vector
> +#error remove the consteval check
> +#endif
> +  if consteval {
> +    return;
> +  }
> +
> +  std::inplace_vector<X, 5> cx;
> +  VERIFY( cx.size() == 0 );
> +  VERIFY( cx.capacity() == 5 );
> +  VERIFY( cx.empty() );
> +  VERIFY( cx.begin() == cx.end() );
> +
> +  std::inplace_vector<X, 0> cx0;
> +  VERIFY( cx0.size() == 0 );
> +  VERIFY( cx0.capacity() == 0 );
> +  VERIFY( cx0.empty() );
> +  VERIFY( cx0.begin() == cx0.end() );
> +}
> +
> +constexpr void
> +test_n()
> +{
> +  std::inplace_vector<int, 5> c(2);
> +  VERIFY( c.size() == 2 );
> +  VERIFY( c.capacity() == 5 );
> +  VERIFY( not c.empty() );
> +  VERIFY( c.begin() + 2 == c.end() );
> +  VERIFY( c[0] == 0 );
> +  VERIFY( c[1] == 0 );
> +
> +  std::inplace_vector<int, 2> c2(2);
> +  VERIFY( c2.size() == 2 );
> +  VERIFY( c2.capacity() == 2 );
> +  VERIFY( not c2.empty() );
> +  VERIFY( c2.begin() + 2 == c2.end() );
> +  VERIFY( c2[0] == 0 );
> +  VERIFY( c2[1] == 0 );
> +
> +  std::inplace_vector<int, 0> c0(0);
> +  VERIFY( c0.size() == 0 );
> +  VERIFY( c0.capacity() == 0 );
> +  VERIFY( c0.empty() );
> +  VERIFY( c0.begin() == c0.end() );
> +
> +  std::inplace_vector<int, 2> c20(0);
> +  VERIFY( c20.size() == 0 );
> +  VERIFY( c20.capacity() == 2 );
> +  VERIFY( c20.empty() );
> +  VERIFY( c20.begin() == c20.end() );
> +
> +  std::inplace_vector<Z, 0> z0(0);
> +  VERIFY( z0.size() == 0 );
> +  VERIFY( z0.capacity() == 0 );
> +  VERIFY( z0.empty() );
> +  VERIFY( z0.begin() == z0.end() );
> +
> +#ifdef __cpp_exceptions
> +#ifdef __cpp_lib_constexpr_exceptions
> +#error remove the consteval check
> +#endif
> +  if not consteval {
> +    try
> +    {
> +      std::inplace_vector<int, 2> ct(3);
> +      VERIFY(false);
> +    }
> +    catch (std::bad_alloc const&)
> +    {
> +    }
> +
> +    try
> +    {
> +      std::inplace_vector<int, 0> ct(1);
> +      VERIFY(false);
> +    }
> +    catch (std::bad_alloc const&)
> +    {
> +    }
> +
> +  }
> +#endif
> +
> +#ifdef __cpp_lib_constexpr_inplace_vector
> +#error remove the consteval check
> +#endif
> +  if consteval {
> +    return;
> +  }
> +
> +  std::inplace_vector<X, 5> cx(3);
> +  VERIFY( cx.size() == 3 );
> +  VERIFY( cx.capacity() == 5 );
> +  VERIFY( not cx.empty() );
> +  VERIFY( cx.begin() + 3 == cx.end() );
> +  (void) cx[2];
> +}
> +
> +constexpr void
> +test_n_val()
> +{
> +  std::inplace_vector<int, 5> c(2, 99);
> +  VERIFY( c.size() == 2 );
> +  VERIFY( c.capacity() == 5 );
> +  VERIFY( not c.empty() );
> +  VERIFY( c.begin() + 2 == c.end() );
> +  VERIFY( c[0] == 99 );
> +  VERIFY( c[1] == 99 );
> +
> +  std::inplace_vector<int, 1> c1(1, 44);
> +  VERIFY( c1.size() == 1 );
> +  VERIFY( c1.capacity() == 1 );
> +  VERIFY( not c1.empty() );
> +  VERIFY( c1.begin() + 1 == c1.end() );
> +  VERIFY( c1[0] == 44 );
> +
> +  std::inplace_vector<int, 0> c0(0, 33);
> +  VERIFY( c0.size() == 0 );
> +  VERIFY( c0.capacity() == 0 );
> +  VERIFY( c0.empty() );
> +  VERIFY( c0.begin() == c0.end() );
> +
> +  std::inplace_vector<int, 2> c20(0, 22);
> +  VERIFY( c20.size() == 0 );
> +  VERIFY( c20.capacity() == 2 );
> +  VERIFY( c20.empty() );
> +  VERIFY( c20.begin() == c20.end() );
> +
> +  std::inplace_vector<Z, 0> z0(0, 33);
> +  VERIFY( z0.size() == 0 );
> +  VERIFY( z0.capacity() == 0 );
> +  VERIFY( z0.empty() );
> +  VERIFY( z0.begin() == z0.end() );
> +
> +#ifdef __cpp_exceptions
> +#ifdef __cpp_lib_constexpr_exceptions
> +#error remove the consteval check
> +#endif
> +  if not consteval {
> +    try
> +    {
> +      std::inplace_vector<int, 2> ct(3, 11);
> +      VERIFY(false);
> +    }
> +    catch (std::bad_alloc const&)
> +    {
> +    }
> +
> +    try
> +    {
> +      std::inplace_vector<int, 0> ct(2, 11);
> +      VERIFY(false);
> +    }
> +    catch (std::bad_alloc const&)
> +    {
> +    }
> +  }
> +#endif
> +
> +#ifdef __cpp_lib_constexpr_inplace_vector
> +#error remove the consteval check
> +#endif
> +  if consteval {
> +    return;
> +  }
> +
> +  std::inplace_vector<X, 5> cx(4);
> +  VERIFY( cx.size() == 4 );
> +  VERIFY( cx.capacity() == 5 );
> +  VERIFY( not cx.empty() );
> +  VERIFY( cx.begin() + 4 == cx.end() );
> +  (void) cx[3];
> +}
> +
> +constexpr void
> +test_initializer_list()
> +{
> +  std::inplace_vector<int, 5> c{22, 33};
> +  VERIFY( c.size() == 2 );
> +  VERIFY( c.capacity() == 5 );
> +  VERIFY( not c.empty() );
> +  VERIFY( c.begin() + 2 == c.end() );
> +  VERIFY( c[0] == 22 );
> +  VERIFY( c[1] == 33 );
> +
> +  std::inplace_vector<int, 1> c1{44};
> +  VERIFY( c1.size() == 1 );
> +  VERIFY( c1.capacity() == 1 );
> +  VERIFY( not c1.empty() );
> +  VERIFY( c1.begin() + 1 == c1.end() );
> +  VERIFY( c1[0] == 44 );
> +
> +  std::inplace_vector<int, 0> c0({});
> +  VERIFY( c0.size() == 0 );
> +  VERIFY( c0.capacity() == 0 );
> +  VERIFY( c0.empty() );
> +  VERIFY( c0.begin() == c0.end() );
> +
> +  std::inplace_vector<int, 2> c20({});
> +  VERIFY( c20.size() == 0 );
> +  VERIFY( c20.capacity() == 2 );
> +  VERIFY( c20.empty() );
> +  VERIFY( c20.begin() == c20.end() );
> +
> +  std::inplace_vector<Z, 0> z0({});
> +  VERIFY( z0.size() == 0 );
> +  VERIFY( z0.capacity() == 0 );
> +  VERIFY( z0.empty() );
> +  VERIFY( z0.begin() == z0.end() );
> +
> +#ifdef __cpp_exceptions
> +#ifdef __cpp_lib_constexpr_exceptions
> +#error remove the consteval check
> +#endif
> +  if not consteval {
> +    try
> +    {
> +      std::inplace_vector<int, 2> ct{11, 22, 33};
> +      VERIFY(false);
> +    }
> +    catch (std::bad_alloc const&)
> +    {
> +    }
> +
> +    try
> +    {
> +      std::inplace_vector<int, 0> ct{11, 22};
> +      VERIFY(false);
> +    }
> +    catch (std::bad_alloc const&)
> +    {
> +    }
> +  }
> +#endif
> +
> +#ifdef __cpp_lib_constexpr_inplace_vector
> +#error remove the consteval check
> +#endif
> +  if consteval {
> +    return;
> +  }
> +
> +  std::inplace_vector<X, 5> cx{X(), X(), X(), X()};
> +  VERIFY( cx.size() == 4 );
> +  VERIFY( cx.capacity() == 5 );
> +  VERIFY( not cx.empty() );
> +  VERIFY( cx.begin() + 4 == cx.end() );
> +  (void) cx[3];
> +}
> +
> +constexpr std::inplace_vector<int, 0> e0;
> +constexpr std::inplace_vector<X, 0> e1;
> +constexpr std::inplace_vector<Z, 0> e2;
> +
> +constexpr std::inplace_vector<int, 5> g1;
> +constexpr std::inplace_vector<int, 5> g2(2, 100);
> +constexpr std::inplace_vector<int, 5> g3 = g2;
> +constexpr std::inplace_vector<int, 5> g4{1, 2, 3};
> +constexpr std::inplace_vector<int, 5> g5 = [] {
> +  std::inplace_vector<int, 5> res;
> +  res = g3;
> +  return res;
> +}();
> +
> +int main()
> +{
> +  auto tests = [] {
> +    test_default();
> +    test_n();
> +    test_n_val();
> +    test_initializer_list();
> +    return true;
> +  };
> +
> +  tests();
> +  constexpr bool _ = tests();
> +}
> diff --git 
> a/libstdc++-v3/testsuite/23_containers/inplace_vector/cons/from_range.cc 
> b/libstdc++-v3/testsuite/23_containers/inplace_vector/cons/from_range.cc
> new file mode 100644
> index 00000000000..73b8d3b6307
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/cons/from_range.cc
> @@ -0,0 +1,186 @@
> +// { dg-do run { target c++26 } }
> +
> +#include <inplace_vector>
> +
> +#include <span>
> +#include <testsuite_hooks.h>
> +#include <testsuite_iterators.h>
> +#include <testsuite_allocator.h>
> +
> +template<typename T, typename V, size_t N>
> +constexpr bool
> +eq(const std::inplace_vector<V, N>& l, std::span<const T> r) {
> +  if (l.size() != r.size())
> +    return false;
> +  for (auto i = 0u; i < l.size(); ++i)
> +    if (l[i] != r[i])
> +      return false;
> +  return true;
> +};
> +
> +template<typename T, template<class TT> class ItType>
> +constexpr void
> +do_test_it()
> +{
> +  // The vector's value_type.
> +  using V = int;
> +
> +  T a[]{1,2,3,4,5,6,7,8,9};
> +  using It = ItType<T>;
> +
> +  auto bounds = typename It::ContainerType(a, a+9);
> +  std::inplace_vector<V, 0> e0(It(a, &bounds), It(a, &bounds));
> +  VERIFY( e0.empty() );
> +
> +  bounds = typename It::ContainerType(a, a+9);
> +  std::inplace_vector<V, 10> v0(It(a, &bounds), It(a, &bounds));
> +  VERIFY( v0.empty() );
> +
> +  bounds = typename It::ContainerType(a, a+9);
> +  std::inplace_vector<V, 10> v4(It(a, &bounds), It(a+4, &bounds));
> +  VERIFY( eq<T>(v4, {a, 4}) );
> +
> +#ifdef __cpp_exceptions
> +#ifdef __cpp_lib_constexpr_exceptions
> +#error remove the consteval check
> +#endif
> +  if consteval {
> +    return;
> +  }
> +
> +  bounds = typename It::ContainerType(a, a+9);
> +  try
> +  {
> +    std::inplace_vector<int, 5> v9(It(a, &bounds), It(a+9, &bounds));
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +
> +  bounds = typename It::ContainerType(a, a+9);
> +  try
> +  {
> +    std::inplace_vector<int, 0> v2(It(a, &bounds), It(a+2, &bounds));
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +#endif
> +}
> +
> +bool
> +test_iterators()
> +{
> +  using namespace __gnu_test;
> +
> +  do_test_it<int, input_iterator_wrapper>();
> +  do_test_it<int, forward_iterator_wrapper>();
> +  do_test_it<int, random_access_iterator_wrapper>();
> +  
> +  do_test_it<short, forward_iterator_wrapper>();
> +  return true;
> +}
> +
> +template<typename Range>
> +constexpr void
> +do_test_r()
> +{
> +  // The vector's value_type.
> +  using V = int;
> +
> +  // The range's value_type.
> +  using T = std::ranges::range_value_t<Range>;
> +  T a[]{1,2,3,4,5,6,7,8,9};
> +
> +  std::inplace_vector<V, 0> e0(std::from_range, Range(a, a+0));
> +  VERIFY( e0.empty() );
> +
> +  std::inplace_vector<V, 10> v0(std::from_range, Range(a, a+0));
> +  VERIFY( v0.empty() );
> +
> +  std::inplace_vector<V, 10> v4(std::from_range, Range(a, a+4));
> +  VERIFY( eq<T>(v4, {a, 4}) );
> +
> +#ifdef __cpp_exceptions
> +#ifdef __cpp_lib_constexpr_exceptions
> +#error remove the consteval check
> +#endif
> +  if consteval {
> +    return;
> +  }
> +  
> +  try
> +  {
> +    std::inplace_vector<V, 5> v9(std::from_range, Range(a, a+9));
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +
> +  try
> +  {
> +    std::inplace_vector<V, 0> v3(std::from_range, Range(a, a+3));
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +#endif
> +}
> +
> +bool
> +test_ranges()
> +{
> +  using namespace __gnu_test;
> +
> +  do_test_r<test_forward_range<int>>();
> +  do_test_r<test_sized_range_sized_sent<int, forward_iterator_wrapper>>();
> +
> +  do_test_r<test_input_range<int>>();
> +  do_test_r<test_input_sized_range<int>>();
> +  do_test_r<test_sized_range_sized_sent<int, input_iterator_wrapper>>();
> +
> +  do_test_r<test_range<int, input_iterator_wrapper_nocopy>>();
> +  do_test_r<test_sized_range<int, input_iterator_wrapper_nocopy>>();
> +  do_test_r<test_sized_range_sized_sent<int, 
> input_iterator_wrapper_nocopy>>();
> +
> +  do_test_r<test_forward_range<short>>();
> +  do_test_r<test_input_range<short>>();
> +
> +  // Not lvalue-convertible to int
> +  struct C {
> +    C(int v) : val(v) { }
> +    operator int() && { return val; }
> +    bool operator==(int b) const { return b == val; }
> +    int val;
> +  };
> +  using rvalue_input_range = test_range<C, input_iterator_wrapper_rval>;
> +  do_test_r<rvalue_input_range>();
> +
> +  return true;
> +}
> +
> +constexpr bool
> +test_constexpr()
> +{
> +  // XXX: this doesn't test the non-forward_range code paths are constexpr.
> +  std::initializer_list<int> il{1, 2, 3, 4};
> +  std::inplace_vector<int, 6> v(il.begin(), il.end());
> +  eq<int>(v, il);
> +
> +  do_test_r<std::span<short>>();
> +  return true;
> +}
> +
> +int main()
> +{
> +  test_iterators();
> +  test_ranges();
> +  static_assert( test_constexpr() );
> +}
> +
> +// Bug PR121143
> +// { dg-prune-output "warning: iteration 5 invokes undefined behavior" }
> diff --git 
> a/libstdc++-v3/testsuite/23_containers/inplace_vector/cons/throws.cc 
> b/libstdc++-v3/testsuite/23_containers/inplace_vector/cons/throws.cc
> new file mode 100644
> index 00000000000..fd4e51f17c4
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/cons/throws.cc
> @@ -0,0 +1,131 @@
> +// { dg-do run { target c++26 } }
> +
> +#include <inplace_vector>
> +
> +#include <span>
> +#include <testsuite_hooks.h>
> +#include <testsuite_iterators.h>
> +#include <testsuite_allocator.h>
> +
> +struct CopyFailed {};
> +
> +struct Thrower
> +{
> +  static inline size_t throw_after = 0;
> +  static inline size_t incontainer = 0;
> +
> +  Thrower() {}
> +  Thrower(int x) {}
> +  Thrower(const Thrower&)
> +  {
> +    if (incontainer >= throw_after)
> +      throw CopyFailed();
> +    ++incontainer;
> +  }
> +
> +  ~Thrower()
> +  { --incontainer; }
> +};
> +
> +template<template<class TT> class ItType>
> +void
> +do_test_it()
> +{
> +  // The vector's value_type.
> +  using V = Thrower;
> +
> +  V a[]{1,2,3,4,5,6,7,8,9};
> +  using It = ItType<V>;
> +
> +  auto bounds = typename It::ContainerType(a, a+9);
> +  Thrower::throw_after = 100;
> +  Thrower::incontainer = 0;
> +  try
> +  {
> +    std::inplace_vector<V, 5> v9(It(a, &bounds), It(a+9, &bounds));
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( Thrower::incontainer == 0 );
> +
> +  bounds = typename It::ContainerType(a, a+9);
> +  Thrower::throw_after = 2;
> +  Thrower::incontainer = 0;
> +  try
> +  {
> +    std::inplace_vector<V, 5> v2(It(a, &bounds), It(a+3, &bounds));
> +    VERIFY(false);
> +  }
> +  catch (CopyFailed const&)
> +  {
> +  }
> +  VERIFY( Thrower::incontainer == 0 );
> +}
> +
> +bool
> +test_iterators()
> +{
> +  using namespace __gnu_test;
> +  do_test_it<input_iterator_wrapper>();
> +  do_test_it<forward_iterator_wrapper>();
> +  do_test_it<random_access_iterator_wrapper>();
> +  return true;
> +}
> +
> +template<typename Range>
> +void
> +do_test_r()
> +{
> +  // The vector's value_type.
> +  using V = Thrower;
> +
> +  V a[]{1,2,3,4,5,6,7,8,9};
> +
> +  Thrower::throw_after = 100;
> +  Thrower::incontainer = 0;
> +  try
> +  {
> +    std::inplace_vector<V, 5> v9(std::from_range, Range(a, a+9));
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( Thrower::incontainer == 0 );
> +
> +  Thrower::throw_after = 2;
> +  Thrower::incontainer = 0;
> +  try
> +  {
> +    std::inplace_vector<V, 5> v9(std::from_range, Range(a, a+3));
> +    VERIFY(false);
> +  }
> +  catch (CopyFailed const&)
> +  {
> +  }
> +  VERIFY( Thrower::incontainer == 0 );
> +}
> +
> +bool
> +test_ranges()
> +{
> +  using namespace __gnu_test;
> +  do_test_r<test_forward_range<Thrower>>();
> +  do_test_r<test_sized_range_sized_sent<Thrower, 
> forward_iterator_wrapper>>();
> +
> +  do_test_r<test_input_range<Thrower>>();
> +  do_test_r<test_input_sized_range<Thrower>>();
> +  do_test_r<test_sized_range_sized_sent<Thrower, input_iterator_wrapper>>();
> +  return true;
> +}
> +
> +int main()
> +{
> +  test_iterators();
> +  test_ranges();
> +}
> +
> +// Bug PR121143
> +// { dg-prune-output "warning: iteration 5 invokes undefined behavior" }
> diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/copy.cc 
> b/libstdc++-v3/testsuite/23_containers/inplace_vector/copy.cc
> new file mode 100644
> index 00000000000..d149e63970c
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/copy.cc
> @@ -0,0 +1,247 @@
> +// { dg-do run { target c++26 } }
> +
> +#include <inplace_vector>
> +#include <ranges>
> +#include <testsuite_hooks.h>
> +
> +struct X
> +{
> +  X() = default;
> +  constexpr X(int p) : v(p) {}
> +  constexpr X(const X& o) : v(o.v) { } // not trivial
> +  constexpr X& operator=(const X& o) // not trivial
> +  { v = o.v; return *this; }
> +
> +  int v;
> +
> +  friend auto operator<=>(const X&, const X&) = default;
> +};
> +
> +template<bool CNoex, bool ANoex>
> +struct N
> +{
> +  N() = default;
> +  constexpr N(const N&) noexcept(CNoex) { } // not trivial
> +  constexpr N& operator=(const N& o) noexcept(ANoex) // not trivial
> +  { return *this; }
> +};
> +
> +struct D
> +{
> +  D() = default;
> +  D(const D&) = default;
> +  D& operator=(const D&) = default;
> +  ~D() {} // not trivially destructible
> +};
> +
> +struct U
> +{
> +  U() = default;
> +  U(const U&) noexcept(false) = default; // lies about noexcept, is trivial 
> but throwing
> +  U& operator=(const U&) noexcept(false) = default; // lies about noexcept, 
> is trivial but throwing
> +};
> +
> +// n5008 inplace.vector.overview p5 says for inplace_vector<T, 0>
> +// provides trivial copy/move/default cosntructpr regardless of T
> +struct Z
> +{
> +  Z(Z&&) = delete;
> +  Z& operator=(Z&&) = delete;
> +};
> +
> +template<size_t N, typename T>
> +  constexpr std::inplace_vector<T, N> const&
> +  materialize(std::inplace_vector<T, N> const& r)
> +  { return r; }
> +
> +static_assert(std::is_copy_constructible_v<std::inplace_vector<int, 2>>);
> +static_assert(std::is_copy_constructible_v<std::inplace_vector<X, 2>>);
> +static_assert(std::is_copy_constructible_v<std::inplace_vector<N<false, 
> false>, 2>>);
> +static_assert(std::is_copy_constructible_v<std::inplace_vector<D, 2>>);
> +static_assert(std::is_copy_constructible_v<std::inplace_vector<U, 2>>);
> +// The operators are not constrained, as for any other container
> +static_assert(std::is_copy_constructible_v<std::inplace_vector<Z, 2>>);
> +
> +// conditional noexcept here is libstdc++ extension,
> +static_assert(std::is_nothrow_copy_constructible_v<std::inplace_vector<int, 
> 2>>);
> +static_assert(!std::is_nothrow_copy_constructible_v<std::inplace_vector<X, 
> 2>>);
> +static_assert(std::is_nothrow_copy_constructible_v<std::inplace_vector<N<true,
>  true>, 2>>);
> +static_assert(std::is_nothrow_copy_constructible_v<std::inplace_vector<N<true,
>  false>, 2>>);
> +static_assert(!std::is_nothrow_copy_constructible_v<std::inplace_vector<N<false,
>  true>, 2>>);
> +static_assert(!std::is_nothrow_copy_constructible_v<std::inplace_vector<N<false,
>  false>, 2>>);
> +static_assert(std::is_nothrow_copy_constructible_v<std::inplace_vector<D, 
> 2>>);
> +static_assert(!std::is_nothrow_copy_constructible_v<std::inplace_vector<U, 
> 2>>);
> +
> +static_assert(std::is_trivially_copy_constructible_v<std::inplace_vector<int,
>  2>>);
> +static_assert(!std::is_trivially_copy_constructible_v<std::inplace_vector<X, 
> 2>>);
> +static_assert(!std::is_trivially_copy_constructible_v<std::inplace_vector<N<true,
>  true>, 2>>);
> +// is_trivially_copy_constructible_v checks destructor
> +static_assert(!std::is_trivially_copy_constructible_v<std::inplace_vector<D, 
> 2>>);
> +static_assert(std::is_trivially_copy_constructible_v<std::inplace_vector<U, 
> 2>>);
> +
> +static_assert(std::is_copy_assignable_v<std::inplace_vector<int, 2>>);
> +static_assert(std::is_copy_assignable_v<std::inplace_vector<X, 2>>);
> +static_assert(std::is_copy_assignable_v<std::inplace_vector<N<false, false>, 
> 2>>);
> +static_assert(std::is_copy_assignable_v<std::inplace_vector<D, 2>>);
> +static_assert(std::is_copy_assignable_v<std::inplace_vector<U, 2>>);
> +// The operators are not constrained, as for any other container
> +static_assert(std::is_copy_assignable_v<std::inplace_vector<Z, 2>>);
> +
> +static_assert(std::is_nothrow_copy_assignable_v<std::inplace_vector<int, 
> 2>>);
> +static_assert(!std::is_nothrow_copy_assignable_v<std::inplace_vector<X, 2>>);
> +static_assert(std::is_nothrow_copy_assignable_v<std::inplace_vector<N<true, 
> true>, 2>>);
> +static_assert(!std::is_nothrow_copy_assignable_v<std::inplace_vector<N<true, 
> false>, 2>>);
> +static_assert(!std::is_nothrow_copy_assignable_v<std::inplace_vector<N<false,
>  true>, 2>>);
> +static_assert(!std::is_nothrow_copy_assignable_v<std::inplace_vector<N<false,
>  false>, 2>>);
> +static_assert(std::is_nothrow_copy_assignable_v<std::inplace_vector<D, 2>>);
> +static_assert(!std::is_nothrow_copy_assignable_v<std::inplace_vector<U, 2>>);
> +
> +// conditional noexcept here is libstdc++ extension,
> +static_assert(std::is_trivially_copy_assignable_v<std::inplace_vector<int, 
> 2>>);
> +static_assert(!std::is_trivially_copy_assignable_v<std::inplace_vector<X, 
> 2>>);
> +static_assert(!std::is_trivially_copy_assignable_v<std::inplace_vector<N<true,
>  true>, 2>>);
> +// destructor is not trivial
> +static_assert(!std::is_trivially_copy_assignable_v<std::inplace_vector<D, 
> 2>>);
> +static_assert(std::is_trivially_copy_assignable_v<std::inplace_vector<U, 
> 2>>);
> +
> +static_assert(std::is_nothrow_copy_constructible_v<std::inplace_vector<int, 
> 0>>);
> +static_assert(std::is_nothrow_copy_constructible_v<std::inplace_vector<X, 
> 0>>);
> +static_assert(std::is_nothrow_copy_constructible_v<std::inplace_vector<N<false,
>  false>, 0>>);
> +static_assert(std::is_nothrow_copy_constructible_v<std::inplace_vector<D, 
> 0>>);
> +static_assert(std::is_nothrow_copy_constructible_v<std::inplace_vector<U, 
> 0>>);
> +static_assert(std::is_nothrow_copy_constructible_v<std::inplace_vector<Z, 
> 0>>);
> +
> +static_assert(std::is_trivially_copy_constructible_v<std::inplace_vector<int,
>  0>>);
> +static_assert(std::is_trivially_copy_constructible_v<std::inplace_vector<X, 
> 0>>);
> +static_assert(std::is_trivially_copy_constructible_v<std::inplace_vector<D, 
> 0>>);
> +static_assert(std::is_trivially_copy_constructible_v<std::inplace_vector<U, 
> 0>>);
> +static_assert(std::is_trivially_copy_constructible_v<std::inplace_vector<Z, 
> 0>>);
> +
> +static_assert(std::is_nothrow_copy_assignable_v<std::inplace_vector<int, 
> 0>>);
> +static_assert(std::is_nothrow_copy_assignable_v<std::inplace_vector<X, 0>>);
> +static_assert(std::is_nothrow_copy_assignable_v<std::inplace_vector<N<false, 
> false>, 0>>);
> +static_assert(std::is_nothrow_copy_assignable_v<std::inplace_vector<D, 0>>);
> +static_assert(std::is_nothrow_copy_assignable_v<std::inplace_vector<U, 0>>);
> +static_assert(std::is_nothrow_copy_assignable_v<std::inplace_vector<Z, 0>>);
> +
> +static_assert(std::is_trivially_copy_assignable_v<std::inplace_vector<int, 
> 0>>);
> +static_assert(std::is_trivially_copy_assignable_v<std::inplace_vector<X, 
> 0>>);
> +static_assert(std::is_trivially_copy_assignable_v<std::inplace_vector<N<false,
>  false>, 0>>);
> +static_assert(std::is_trivially_copy_assignable_v<std::inplace_vector<D, 
> 0>>);
> +static_assert(std::is_trivially_copy_assignable_v<std::inplace_vector<U, 
> 0>>);
> +static_assert(std::is_trivially_copy_assignable_v<std::inplace_vector<Z, 
> 0>>);
> +
> +
> +template<typename T, size_t N>
> +constexpr bool
> +eq(const std::inplace_vector<T, N>& s, std::span<const T> o)
> +{ return std::ranges::equal(s, o); }
> +
> +constexpr void
> +test_ctor()
> +{
> +  auto e0 = materialize<0, int>({});
> +  VERIFY( e0.empty() );
> +  auto e1 = materialize<0, X>({});
> +  VERIFY( e1.empty() );
> +  auto e2 = materialize<0, Z>({});
> +  VERIFY( e2.empty() );
> +
> +  auto c0 = materialize<5, int>({});
> +  VERIFY( c0.empty() );
> +
> +  auto c3 = materialize<5, int>({1, 2, 3});
> +  VERIFY( eq(c3, {1, 2, 3}) );
> +
> +  auto c5 = materialize<5, int>({1, 2, 3, 4, 5});
> +  VERIFY( eq(c5, {1, 2, 3, 4, 5}) );
> +
> +#ifdef __cpp_lib_constexpr_inplace_vector
> +#error remove the consteval check
> +#endif
> +  if consteval {
> +    return;
> +  }
> +
> +  auto x0 = materialize<3, X>({});
> +  VERIFY( x0.empty() );
> +
> +  auto x2 = materialize<3, X>({1, 2});
> +  VERIFY( eq(x2, {1, 2}) );
> +
> +  auto x3 = materialize<3, X>({1, 2, 3});
> +  VERIFY( eq(x3, {1, 2, 3}) );
> +}
> +
> +constexpr void
> +test_assign()
> +{
> +  std::inplace_vector<int, 0> e0;
> +  e0 = materialize<0, int>({});
> +  VERIFY( e0.empty() );
> +  std::inplace_vector<X, 0> e1;
> +  e1 = materialize<0, X>({});
> +  VERIFY( e1.empty() );
> +  std::inplace_vector<Z, 0> e2;
> +  e2 = materialize<0, Z>({});
> +  VERIFY( e2.empty() );
> +
> +  std::inplace_vector<int, 5> c;
> +  c = materialize<5, int>({});
> +  VERIFY( c.empty() );
> +
> +  c = materialize<5, int>({1, 2, 3});
> +  VERIFY( eq(c, {1, 2, 3}) );
> +
> +  c = materialize<5, int>({1, 2, 3, 4, 5});
> +  VERIFY( eq(c, {1, 2, 3, 4, 5}) );
> +
> +  c = materialize<5, int>({4, 5});
> +  VERIFY( eq(c, {4, 5}) );
> +
> +  c = materialize<5, int>({});
> +  VERIFY( c.empty() );
> +
> +#ifdef __cpp_lib_constexpr_inplace_vector
> +#error remove the consteval check
> +#endif
> +  if consteval {
> +    return;
> +  }
> +
> +  std::inplace_vector<X, 5> x;
> +  x = materialize<5, X>({});
> +  VERIFY( x.empty() );
> +
> +  x = materialize<5, X>({1, 2, 3});
> +  VERIFY( eq(x, {1, 2, 3}) );
> +
> +  x = materialize<5, X>({1, 2, 3, 4, 5});
> +  VERIFY( eq(x, {1, 2, 3, 4, 5}) );
> +
> +  x = materialize<5, X>({4, 5});
> +  VERIFY( eq(x, {4, 5}) );
> +
> +  x = materialize<5, X>({});
> +  VERIFY( x.empty() );
> +}
> +
> +constexpr auto e0 = materialize<0, int>({});
> +constexpr auto e1 = materialize<0, X>({});
> +constexpr auto e2 = materialize<0, Z>({});
> +
> +constexpr auto t1 = materialize<3, int>({});
> +constexpr auto t2 = materialize<3, int>({1, 2});
> +constexpr auto t3 = materialize<3, int>({11, 22, 33});
> +
> +int main()
> +{
> +  auto tests = [] {
> +    test_ctor();
> +    test_assign();
> +    return true;
> +  };
> +
> +  tests();
> +  constexpr bool _ = tests();
> +}
> diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/erasure.cc 
> b/libstdc++-v3/testsuite/23_containers/inplace_vector/erasure.cc
> new file mode 100644
> index 00000000000..c7fda097896
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/erasure.cc
> @@ -0,0 +1,49 @@
> +// { dg-do run { target c++26 } }
> +
> +#include <inplace_vector>
> +#include <testsuite_hooks.h>
> +
> +constexpr void
> +test_erase()
> +{
> +  std::inplace_vector<int, 15> c{1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1, 4, 4, 9};
> +  std::erase(c, 4);
> +  VERIFY( c.size() == 10 );
> +  std::erase(c, 1);
> +  VERIFY( c.size() == 8 );
> +  std::erase(c, 9);
> +  VERIFY( c.size() == 7 );
> +  VERIFY( (c == std::inplace_vector<int, 15>{2, 3, 5, 6, 5, 3, 2}) );
> +
> +  std::inplace_vector<int, 0> e;
> +  std::erase(e, 10);
> +  VERIFY( e.empty() );
> +}
> +
> +constexpr void
> +test_erase_if()
> +{
> +  std::inplace_vector<int, 15> c{1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1, 4, 4, 9};
> +  std::erase_if(c, [](int i) { return i > 5; });
> +  VERIFY( c.size() == 12 );
> +  std::erase_if(c, [](int i) { return i == 4; });
> +  VERIFY( c.size() == 8 );
> +  std::erase_if(c, [](int i) { return i & 1; });
> +  VERIFY( (c == std::inplace_vector<int, 15>{2, 2}) );
> +
> +  std::inplace_vector<int, 0> e;
> +  std::erase_if(e, [](int i) { return i > 5; });
> +  VERIFY( e.empty() );
> +}
> +
> +int main()
> +{
> +  test_erase();
> +  test_erase_if();
> +
> +  constexpr bool _ = [] {
> +    test_erase();
> +    test_erase_if();
> +    return true;
> +  }();
> +}
> diff --git 
> a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/assign.cc 
> b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/assign.cc
> new file mode 100644
> index 00000000000..91132be550e
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/assign.cc
> @@ -0,0 +1,386 @@
> +// { dg-do run { target c++26 } }
> +
> +#include <inplace_vector>
> +
> +#include <span>
> +#include <testsuite_hooks.h>
> +#include <testsuite_iterators.h>
> +
> +struct X
> +{
> +  X() = default;
> +  constexpr X(int p) : v(p) {}
> +  constexpr X(const X& o) : v(o.v) { } // not trivial
> +  constexpr X& operator=(const X& o) // not trivial
> +  { v = o.v; return *this; }
> +
> +  int v;
> +
> +  friend auto operator<=>(const X&, const X&) = default;
> +};
> +
> +template<typename T, typename V, size_t N>
> +constexpr bool
> +eq(const std::inplace_vector<V, N>& l, std::span<const T> r) {
> +  if (l.size() != r.size())
> +    return false;
> +  for (auto i = 0u; i < l.size(); ++i)
> +    if (l[i] != r[i])
> +      return false;
> +  return true;
> +};
> +
> +template<size_t N, typename T, template<class TT> class ItType>
> +constexpr void
> +test_assign_empty_it()
> +{
> +  using namespace __gnu_test;
> +
> +  T a[]{1,2,3,4,5,6,7,8,9,10};
> +  using It = ItType<T>;
> +  using Range = test_range<T, ItType>;
> +  using SizedRange = test_sized_range<T, ItType>;
> +
> +  const std::inplace_vector<T, N> src(std::from_range, std::span(a, N));
> +  std::inplace_vector<T, N> v;
> +
> +  v = src;
> +  v.assign_range(Range(a, a));
> +  VERIFY( v.empty() );
> +  v.assign_range(Range(a, a));
> +  VERIFY( v.empty() );
> +
> +  v = src;
> +  v.assign_range(SizedRange(a, a));
> +  VERIFY( v.empty() );
> +
> +  v = src;
> +  auto bounds = typename It::ContainerType(a, a+9);
> +  v.assign(It(a, &bounds), It(a, &bounds));
> +  VERIFY( v.empty() );
> +
> +#ifdef __cpp_exceptions
> +#ifdef __cpp_lib_constexpr_exceptions
> +#error remove the consteval check
> +#endif
> +  if consteval {
> +    return;
> +  }
> +
> +  static_assert(N < 9);
> +
> +  v = src;
> +  try
> +  {
> +    v.assign_range(Range(a, a+9));
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  if constexpr (std::ranges::sized_range<Range> || 
> std::ranges::forward_range<Range>)
> +    VERIFY( eq<T>(v, {a, N}) );
> +
> +  v = src;
> +  try
> +  {
> +    v.assign_range(SizedRange(a, a+9));
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( eq<T>(v, {a, N}) );
> +
> +  v = src;
> +  bounds = typename It::ContainerType(a, a+9);
> +  try
> +  {
> +    v.assign(It(a, &bounds), It(a+9, &bounds));
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  if constexpr(std::forward_iterator<It>)
> +    VERIFY( eq<T>(v, {a, N}) );
> +#endif
> +}
> +
> +template<size_t N, typename T>
> +constexpr void
> +test_assign_empty_other()
> +{
> +  T a[]{1,2,3,4,5,6,7,8,9,10};
> +  const std::inplace_vector<T, N> src(std::from_range, std::span(a, N));
> +  std::inplace_vector<T, N> v;
> +
> +  v = src;
> +  v.assign(0, T(4));
> +  VERIFY( v.empty() );
> +
> +  v = src;
> +  v.assign({});
> +  VERIFY( v.empty() );
> +
> +  v = src;
> +  v = {};
> +  VERIFY( v.empty() );
> +
> +  v = src;
> +  v.resize(0, T(3));
> +  VERIFY( v.empty() );
> +
> +  v = src;
> +  v.resize(0);
> +  VERIFY( v.empty() );
> +
> +#ifdef __cpp_exceptions
> +#ifdef __cpp_lib_constexpr_exceptions
> +#error remove the consteval check
> +#endif
> +  if consteval {
> +    return;
> +  }
> +
> +  static_assert(N < 9);
> +
> +  v = src;
> +  try
> +  {
> +    v.assign(9, T(4));
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( eq<T>(v, {a, N}) );
> +
> +  std::initializer_list<T> il =
> +  {T(0), T(1), T(2), T(3), T(4), T(5), T(6), T(7), T(8), T(9), T(10)};
> +  try
> +  {
> +    v.assign(il);
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( eq<T>(v, {a, N}) );
> +
> +  try
> +  {
> +    v = il;
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( eq<T>(v, {a, N}) );
> +
> +  try
> +  {
> +    v.resize(9, T(3));
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( eq<T>(v, {a, N}) );
> +
> +  try
> +  {
> +    v.resize(9);
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( eq<T>(v, {a, N}) );
> +#endif
> +}
> +
> +template<size_t N, typename T>
> +constexpr void
> +test_assign_empty()
> +{
> +  // TODO make test iterators consteval
> +  if !consteval
> +  {
> +    using namespace __gnu_test;
> +    test_assign_empty_it<N, T, input_iterator_wrapper>();
> +    test_assign_empty_it<N, T, forward_iterator_wrapper>();
> +    test_assign_empty_it<N, T, random_access_iterator_wrapper>();
> +  }
> +
> +  test_assign_empty_other<N, T>;
> +}
> +
> +template<typename Range>
> +constexpr void
> +test_assign_range()
> +{
> +  using T = std::ranges::range_value_t<Range>;
> +  T a[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
> +
> +  std::inplace_vector<T, 10> v;
> +  v.assign_range(Range(a,a+5));
> +  VERIFY( eq<T>(v, {a, 5}) );
> +
> +  v.assign_range(Range(a,a+7));
> +  VERIFY( eq<T>(v, {a, 7}) );
> +
> +  v.assign_range(Range(a,a+3));
> +  VERIFY( eq<T>(v, {a, 3}) );
> +
> +  v.assign_range(Range(a,a+10));
> +  VERIFY( eq<T>(v, {a, 10}) );
> +}
> +
> +template<typename T, template<class TT> class ItType>
> +constexpr void
> +test_assign_iterators()
> +{
> +  T a[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
> +  using It = ItType<T>;
> +
> +  std::inplace_vector<T, 10> v;
> +
> +  auto bounds = typename It::ContainerType(a, a+15);
> +  v.assign(It(a, &bounds), It(a+5, &bounds));
> +  VERIFY( eq<T>(v, {a, 5}) );
> +
> +  bounds = typename It::ContainerType(a, a+15);
> +  v.assign(It(a, &bounds), It(a+7, &bounds));
> +  VERIFY( eq<T>(v, {a, 7}) );
> +
> +  bounds = typename It::ContainerType(a, a+15);
> +  v.assign(It(a, &bounds), It(a+3, &bounds));
> +  VERIFY( eq<T>(v, {a, 3}) );
> +
> +  bounds = typename It::ContainerType(a, a+15);
> +  v.assign(It(a, &bounds), It(a+10, &bounds));
> +  VERIFY( eq<T>(v, {a, 10}) );
> +}
> +
> +template<typename T>
> +constexpr void
> +test_assign_initializer_list()
> +{
> +  T a[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
> +
> +  std::inplace_vector<T, 10> v;
> +
> +  v.assign({T(1), T(2), T(3), T(4), T(5)});
> +  VERIFY( eq<T>(v, {a, 5}) );
> +
> +  v = {T(1), T(2), T(3), T(4), T(5), T(6), T(7)};
> +  VERIFY( eq<T>(v, {a, 7}) );
> +
> +  v.assign({T(1), T(2), T(3)});
> +  VERIFY( eq<T>(v, {a, 3}) );
> +
> +  v = {T(1), T(2), T(3), T(4), T(5), T(6), T(7), T(8), T(9), T(10)};
> +  VERIFY( eq<T>(v, {a, 10}) );
> +}
> +
> +template<typename T>
> +constexpr void
> +test_assign_repeated()
> +{
> +  auto rep = [](const std::inplace_vector<T, 10>& v, size_t c, const T& t)
> +  {
> +    if (v.size() != c)
> +      return false;
> +    for (const T& o : v)
> +      if (o != t)
> +     return false;
> +    return true;
> +  };
> +
> +  std::inplace_vector<T, 10> v;
> +
> +  v.assign(5, T(1));
> +  VERIFY( rep(v, 5, T(1)) );
> +
> +  v.assign(7, T(2));
> +  VERIFY( rep(v, 7, T(2)) );
> +
> +  v.assign(3, T(4));
> +  VERIFY( rep(v, 3, T(4)) );
> +
> +  v.assign(10, T(8));
> +  VERIFY( rep(v, 10, T(8)) );
> +}
> +
> +template<typename T>
> +constexpr void
> +test_resize()
> +{
> +  T a[]{1,1,1,1,2,2,2,0,0,0};
> +
> +  std::inplace_vector<T, 10> v;
> +
> +  v.resize(4, T(1));
> +  VERIFY( eq<T>(v, {a, 4}) );
> +
> +  v.resize(7, T(2));
> +  VERIFY( eq<T>(v, {a, 7}) );
> +
> +  v.resize(10);
> +  VERIFY( eq<T>(v, {a, 10}) );
> +
> +  v.resize(6, T(1));
> +  VERIFY( eq<T>(v, {a, 6}) );
> +}
> +
> +template<typename T>
> +constexpr void
> +test_assigns()
> +{
> +  using namespace __gnu_test;
> +  // TODO make test iterators consteval
> +  if !consteval {
> +    test_assign_range<test_forward_range<int>>();
> +    test_assign_range<test_sized_range_sized_sent<int, 
> forward_iterator_wrapper>>();
> +
> +    test_assign_range<test_input_range<int>>();
> +    test_assign_range<test_input_sized_range<int>>();
> +    test_assign_range<test_sized_range_sized_sent<int, 
> input_iterator_wrapper>>();
> +
> +    test_assign_range<test_range<int, input_iterator_wrapper_nocopy>>();
> +    test_assign_range<test_sized_range<int, 
> input_iterator_wrapper_nocopy>>();
> +    test_assign_range<test_sized_range_sized_sent<int, 
> input_iterator_wrapper_nocopy>>();
> +
> +    test_assign_iterators<T, input_iterator_wrapper>();
> +    test_assign_iterators<T, forward_iterator_wrapper>();
> +    test_assign_iterators<T, random_access_iterator_wrapper>();
> +  }
> +
> +  test_assign_initializer_list<T>();
> +  test_assign_repeated<T>();
> +  test_resize<T>();
> +}
> +
> +int main()
> +{
> +  auto test_all = [] {
> +    test_assign_empty<0, int>();
> +    test_assign_empty<0, X>();
> +    test_assign_empty<2, int>();
> +
> +    test_assigns<int>();
> +#ifdef __cpp_lib_constexpr_inplace_vector
> +#error uncomemnt test_inserts<X>()
> +#endif
> +    if !consteval {
> +      test_assign_empty<2, X>();
> +      test_assigns<X>();
> +    }
> +    return true;
> +  };
> +
> +
> +  test_all();
> +  static_assert(test_all());
> +}
> diff --git 
> a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/erase.cc 
> b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/erase.cc
> new file mode 100644
> index 00000000000..8b82ab4189c
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/erase.cc
> @@ -0,0 +1,117 @@
> +// { dg-do run { target c++26 } }
> +
> +#include <inplace_vector>
> +
> +#include <span>
> +#include <testsuite_hooks.h>
> +
> +struct X
> +{
> +  X() = default;
> +  constexpr X(int p) : v(p) {}
> +  constexpr X(const X& o) : v(o.v) { } // not trivial
> +  constexpr X& operator=(const X& o) // not trivial
> +  { v = o.v; return *this; }
> +
> +  int v;
> +
> +  friend auto operator<=>(const X&, const X&) = default;
> +};
> +
> +template<typename T, typename V, size_t N>
> +constexpr bool
> +eq(const std::inplace_vector<V, N>& l, std::span<const T> r) {
> +  if (l.size() != r.size())
> +    return false;
> +  for (auto i = 0u; i < l.size(); ++i)
> +    if (l[i] != r[i])
> +      return false;
> +  return true;
> +};
> +
> +template<typename T, typename V, size_t N>
> +constexpr bool
> +eq(const std::inplace_vector<V, N>& l, std::initializer_list<T> r)
> +{ return eq<T>(l, std::span<const T>(r)); }
> +
> +template<size_t N, typename T>
> +constexpr void
> +test_erase_all_or_none()
> +{
> +  using namespace __gnu_test;
> +
> +  T a[]{1,2,3,4,5,6,7,8,9};
> +  const T c(10);
> +
> +  std::inplace_vector<T, N> src(std::from_range, std::span(a, a+N));
> +  std::inplace_vector<T, N> v;
> +
> +  v = src;
> +  auto it = v.erase(v.begin(), v.begin());
> +  VERIFY( it == v.begin() );
> +  VERIFY( eq<T>(v, {a, N}) );
> +
> +  it = v.erase(v.end(), v.end());
> +  VERIFY( it == v.end() );
> +  VERIFY( eq<T>(v, {a, N}) );
> +
> +  it = v.erase(v.begin(), v.end());
> +  VERIFY( it == v.begin() );
> +  VERIFY( v.empty() );
> +
> +  v = src;
> +  v.clear();
> +  VERIFY( v.empty() );
> +}
> +
> +template<typename T>
> +constexpr void
> +test_erase()
> +{
> +  std::inplace_vector<T, 10> v{T(1), T(2), T(3), T(4), T(5), T(6), T(7)};
> +
> +  auto it = v.erase(v.begin());
> +  VERIFY( eq<T>(v, {T(2), T(3), T(4), T(5), T(6), T(7)}) );
> +  VERIFY( it == v.begin() );
> +
> +  it = v.erase(v.end()-1);
> +  VERIFY( eq<T>(v, {T(2), T(3), T(4), T(5), T(6)}) );
> +  VERIFY( it == v.end() );
> +
> +  it = v.erase(v.begin()+2, v.begin()+4);
> +  VERIFY( eq<T>(v, {T(2), T(3), T(6)}) );
> +  VERIFY( it == v.begin()+2 );
> +
> +  it = v.erase(v.end()-1, v.end());
> +  VERIFY( eq<T>(v, {T(2), T(3)}) );
> +  VERIFY( it == v.end() );
> +
> +  it = v.erase(v.begin(), v.begin()+1);
> +  VERIFY( eq<T>(v, {T(3)}) );
> +  VERIFY( it == v.begin() );
> +
> +  v.pop_back();
> +  VERIFY( v.empty() );
> +}
> +
> +int main()
> +{
> +  auto test_all = [] {
> +    test_erase_all_or_none<0, int>();
> +    test_erase_all_or_none<0, X>();
> +
> +    test_erase_all_or_none<4, int>();
> +
> +    test_erase<int>();
> +#ifdef __cpp_lib_constexpr_inplace_vector
> +#error uncomemnt test_inserts<X>()
> +#endif
> +    if ! consteval {
> +      test_erase_all_or_none<4, X>();
> +    }
> +    return true;
> +  };
> +
> +  test_all();
> +  static_assert(test_all());;
> +}
> diff --git 
> a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc
>  
> b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc
> new file mode 100644
> index 00000000000..072f0b3e095
> --- /dev/null
> +++ 
> b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc
> @@ -0,0 +1,611 @@
> +// { dg-do run { target c++26 } }
> +
> +#include <inplace_vector>
> +
> +#include <span>
> +#include <testsuite_hooks.h>
> +#include <testsuite_iterators.h>
> +
> +struct X
> +{
> +  X() = default;
> +  constexpr X(int p) : v(p) {}
> +  constexpr X(const X& o) : v(o.v) { } // not trivial
> +  constexpr X& operator=(const X& o) // not trivial
> +  { v = o.v; return *this; }
> +
> +  int v;
> +
> +  friend auto operator<=>(const X&, const X&) = default;
> +};
> +
> +template<typename T, typename V, size_t N>
> +constexpr bool
> +eq(const std::inplace_vector<V, N>& l, std::span<const T> r) {
> +  if (l.size() != r.size())
> +    return false;
> +  for (auto i = 0u; i < l.size(); ++i)
> +    if (l[i] != r[i])
> +      return false;
> +  return true;
> +};
> +
> +template<typename T, typename V, size_t N>
> +constexpr bool
> +prefix(const std::inplace_vector<V, N>& l, std::span<const T> r) {
> +  if (l.size() < r.size())
> +    return false;
> +  for (auto i = 0u; i < r.size(); ++i)
> +    if (l[i] != r[i])
> +      return false;
> +  return true;
> +};
> +
> +template<size_t N, typename T, template<class TT> class ItType>
> +constexpr void
> +test_add_to_full_it()
> +{
> +  using namespace __gnu_test;
> +
> +  T a[]{1,2,3,4,5,6,7,8,9};
> +  using It = ItType<T>;
> +  using Range = test_range<T, ItType>;
> +  using SizedRange = test_sized_range<T, ItType>;
> +
> +  std::inplace_vector<T, N> v(std::from_range, std::span(a, a+N));
> +
> +  Range r1(a, a);
> +  auto rit1 = v.try_append_range(r1);
> +  VERIFY( eq<T>(v, {a, N}) );
> +  VERIFY( rit1.base() == a );
> +
> +  SizedRange r2(a, a);
> +  auto rit2 = v.try_append_range(r2);
> +  VERIFY( eq<T>(v, {a, N}) );
> +  VERIFY( rit2.base() == a );
> +
> +  v.append_range(Range(a, a));
> +  VERIFY( eq<T>(v, {a, N}) );
> +  v.append_range(SizedRange(a, a));
> +  VERIFY( eq<T>(v, {a, N}) );
> +
> +  auto it = v.insert_range(v.end(), Range(a, a));
> +  VERIFY( eq<T>(v, {a, N}) );
> +  VERIFY( it == v.end() );
> +  it = v.insert_range(v.end(), SizedRange(a, a));
> +  VERIFY( eq<T>(v, {a, N}) );
> +  VERIFY( it == v.end() );
> +
> +  auto bounds = typename It::ContainerType(a, a+9);
> +  it = v.insert(v.end(), It(a, &bounds), It(a, &bounds));
> +  VERIFY( eq<T>(v, {a, N}) );
> +  VERIFY( it == v.end() );
> +
> +  it = v.insert_range(v.begin(), SizedRange(a, a));
> +  VERIFY( eq<T>(v, {a, N}) );
> +  VERIFY( it == v.begin() );
> +  it = v.insert_range(v.begin(), Range(a, a));
> +  VERIFY( eq<T>(v, {a, N}) );
> +  VERIFY( it == v.begin() );
> +
> +  bounds = typename It::ContainerType(a, a+9);
> +  it = v.insert(v.begin(), It(a, &bounds), It(a, &bounds));
> +  VERIFY( eq<T>(v, {a, N}) );
> +  VERIFY( it == v.begin() );
> +
> +  // Inserting non-empty range
> +  Range r3(a+3, a+5);
> +  auto rit3 = v.try_append_range(r3);
> +  VERIFY( eq<T>(v, {a, N}) );
> +  VERIFY( rit3.base() == a+3 );
> +
> +  SizedRange r4(a+2, a+5);
> +  auto rit4 = v.try_append_range(r4);
> +  VERIFY( eq<T>(v, {a, N}) );
> +  VERIFY( rit4.base() == a+2 );
> +
> +#ifdef __cpp_exceptions
> +#ifdef __cpp_lib_constexpr_exceptions
> +#error remove the consteval check
> +#endif
> +  if consteval {
> +    return;
> +  }
> +
> +  try
> +  {
> +    v.append_range(Range(a, a + 5));
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( eq<T>(v, {a, N}) );
> +
> +  try
> +  {
> +    v.append_range(SizedRange(a, a + 5));
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( eq<T>(v, {a, N}) );
> +
> +  try
> +  {
> +    v.insert_range(v.begin(), SizedRange(a, a+5));
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( eq<T>(v, {a, N}) );
> +
> +  try
> +  {
> +    v.insert_range(v.begin(), Range(a, a+5));
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  auto gn = std::ranges::sized_range<Range> || 
> std::ranges::forward_range<Range> ? N : 0;
> +  VERIFY( prefix<T>(v, {a, gn}) );
> +
> +  v = std::inplace_vector<T, N>(std::from_range, std::span(a, a+N));
> +  try
> +  {
> +    v.insert_range(v.begin(), Range(a, a+5));
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  gn = std::forward_iterator<It> ? N : 0;
> +  VERIFY( prefix<T>(v, {a, gn}) );
> +#endif
> +}
> +
> +template<size_t N, typename T>
> +constexpr void
> +test_add_to_full_other()
> +{
> +  using namespace __gnu_test;
> +
> +  T a[]{1,2,3,4,5,6,7,8,9};
> +  std::inplace_vector<T, N> v(std::from_range, std::span(a, a+N));
> +
> +  auto it = v.insert(v.end(), {});
> +  VERIFY( eq<T>(v, {a, N}) );
> +  VERIFY( it == v.end() );
> +  it = v.insert(v.end(), 0u, T(2));
> +  VERIFY( eq<T>(v, {a, N}) );
> +  VERIFY( it == v.end() );
> +
> +  it = v.insert(v.begin(), {});
> +  VERIFY( eq<T>(v, {a, N}) );
> +  VERIFY( it == v.begin() );
> +  it = v.insert(v.begin(), 0u, T(2));
> +  VERIFY( eq<T>(v, {a, N}) );
> +  VERIFY( it == v.begin() );
> +
> +#ifdef __cpp_exceptions
> +#ifdef __cpp_lib_constexpr_exceptions
> +#error remove the consteval check
> +#endif
> +  if consteval {
> +    return;
> +  }
> +
> +  v = std::inplace_vector<T, N>(std::from_range, std::span(a, a+N));
> +  try
> +  {
> +    v.insert(v.begin(), {T(1), T(2), T(3)});
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( eq<T>(v, {a, N}) );
> +
> +  try
> +  {
> +    v.insert(v.begin(), 4u, T(3));
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( eq<T>(v, {a, N}) );
> +#endif
> +}
> +
> +
> +template<size_t N, typename T>
> +constexpr void
> +test_add_to_full()
> +{
> +  using namespace __gnu_test;
> +  // TODO make test iterators consteval
> +  if !consteval {
> +    test_add_to_full_it<N, T, input_iterator_wrapper>();
> +    test_add_to_full_it<N, T, forward_iterator_wrapper>();
> +    test_add_to_full_it<N, T, random_access_iterator_wrapper>();
> +  }
> +  test_add_to_full_other<N, T>();
> +}
> +
> +template<typename Range>
> +constexpr void
> +test_append_range()
> +{
> +  using T = std::ranges::range_value_t<Range>;
> +  T a[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
> +
> +  std::inplace_vector<T, 20> v;
> +  v.append_range(Range(a,a+10));
> +  VERIFY( eq<T>(v, {a, 10}) );
> +
> +  v.append_range(Range(a+10, a+15));
> +  VERIFY( eq<T>(v, {a, 15}) );
> +
> +#ifdef __cpp_exceptions
> +#ifdef __cpp_lib_constexpr_exceptions
> +#error remove the consteval check
> +#endif
> +  if consteval {
> +    return;
> +  }
> +
> +  try
> +  {
> +    v.append_range(Range(a, a+10));
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( prefix<T>(v, {a, 15}) );
> +#endif
> +}
> +
> +template<typename Range>
> +constexpr void
> +test_try_append_range()
> +{
> +  using T = std::ranges::range_value_t<Range>;
> +  T a[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25};
> +
> +  std::inplace_vector<T, 20> v;
> +  Range r1 = Range(a, a+10);
> +  auto it1 = v.try_append_range(r1);
> +  VERIFY( eq<T>(v, {a, 10}) );
> +  VERIFY( it1.base() == a+10 );
> +
> +  Range r2 = Range(a+10, a+15);
> +  auto it2 = v.try_append_range(r2);
> +  VERIFY( eq<T>(v, {a, 15}) );
> +  VERIFY( it2.base() == a+15 );
> +
> +  Range r3 = Range(a+15, a+25);
> +  auto it3 = v.try_append_range(r3);
> +  VERIFY( eq<T>(v, {a, 20}) );
> +  VERIFY( it3.base() == a+20 );
> +}
> +
> +template<typename Range>
> +constexpr void
> +test_insert_range()
> +{
> +  using T = std::ranges::range_value_t<Range>;
> +  T a[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
> +
> +  std::inplace_vector<T, 20> v;
> +  auto it = v.insert_range(v.begin(), Range(a+10,a+15));
> +  VERIFY( eq<T>(v, {a+10, 5}) );
> +  VERIFY( it == v.begin() );
> +
> +  it = v.insert_range(v.begin(), Range(a, a+5));
> +  VERIFY( prefix<T>(v, {a, 5}) );
> +  VERIFY( it == v.begin() );
> +
> +  it = v.insert_range(v.begin() + 5, Range(a+5, a+10));
> +  VERIFY( eq<T>(v, {a, 15}) );
> +  VERIFY( it == v.begin() + 5 );
> +
> +#ifdef __cpp_exceptions
> +#ifdef __cpp_lib_constexpr_exceptions
> +#error remove the consteval check
> +#endif
> +  if consteval {
> +    return;
> +  }
> +
> +  const bool seg = std::ranges::sized_range<Range> || 
> std::ranges::forward_range<Range>;
> +  auto vc = v;
> +  try
> +  {
> +    vc.insert_range(vc.begin(), Range(a, a+10));
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( prefix<T>(vc, {a, seg ? 15 : 0}) );
> +
> +  vc = v;
> +  try
> +  {
> +    vc.insert_range(vc.begin()+5, Range(a, a+10));
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( prefix<T>(vc, {a, seg ? 15 : 5}) );
> +
> +  vc = v;
> +  try
> +  {
> +    vc.insert_range(vc.end(), Range(a, a+10));
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( prefix<T>(vc, {a, 15}) );
> +#endif
> +}
> +
> +template<typename Range>
> +constexpr void
> +do_test_ranges()
> +{
> +  test_append_range<Range>();
> +  test_try_append_range<Range>();
> +  test_insert_range<Range>();
> +}
> +
> +template<typename T, template<class TT> class ItType>
> +constexpr void
> +test_insert_iterators()
> +{
> +  T a[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
> +  using It = ItType<T>;
> +
> +  std::inplace_vector<T, 20> v;
> +
> +  auto bounds = typename It::ContainerType(a, a+15);
> +  auto it = v.insert(v.begin(), It(a+10, &bounds), It(a+15, &bounds));
> +  VERIFY( eq<T>(v, {a+10, 5}) );
> +  VERIFY( it == v.begin() );
> +
> +  bounds = typename It::ContainerType(a, a+15);
> +  it = v.insert(v.begin(), It(a, &bounds), It(a+5, &bounds));
> +  VERIFY( prefix<T>(v, {a, 5}) );
> +  VERIFY( it == v.begin() );
> +
> +  bounds = typename It::ContainerType(a, a+15);
> +  it = v.insert(v.begin() + 5, It(a+5, &bounds), It(a+10, &bounds));
> +  VERIFY( eq<T>(v, {a, 15}) );
> +  VERIFY( it == v.begin() + 5 );
> +
> +#ifdef __cpp_exceptions
> +#ifdef __cpp_lib_constexpr_exceptions
> +#error remove the consteval check
> +#endif
> +  if consteval {
> +    return;
> +  }
> +
> +  const bool seg = std::forward_iterator<It>;
> +  auto vc = v;
> +  bounds = typename It::ContainerType(a, a+15);
> +  try
> +  {
> +    vc.insert(vc.begin(), It(a, &bounds), It(a+10, &bounds));
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( prefix<T>(vc, {a, seg ? 15 : 0}) );
> +
> +  vc = v;
> +  bounds = typename It::ContainerType(a, a+15);
> +  try
> +  {
> +    vc.insert(vc.begin()+5, It(a, &bounds), It(a+10, &bounds));
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( prefix<T>(vc, {a, seg ? 15 : 5}) );
> +
> +  vc = v;
> +  bounds = typename It::ContainerType(a, a+15);
> +  try
> +  {
> +    vc.insert(vc.end(), It(a, &bounds), It(a+10, &bounds));
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( prefix<T>(vc, {a, 15}) );
> +#endif
> +}
> +
> +template<typename T>
> +constexpr void
> +test_insert_initializer_list()
> +{
> +  T a[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
> +
> +  std::inplace_vector<T, 20> v;
> +
> +  auto it = v.insert(v.begin(), {T(11), T(12), T(13), T(14), T(15)});
> +  VERIFY( eq<T>(v, {a+10, 5}) );
> +  VERIFY( it == v.begin() );
> +
> +  it = v.insert(v.begin(), {T(1), T(2), T(3), T(4), T(5)});
> +  VERIFY( prefix<T>(v, {a, 5}) );
> +  VERIFY( it == v.begin() );
> +
> +  it = v.insert(v.begin() + 5, {T(6), T(7), T(8), T(9), T(10)});
> +  VERIFY( eq<T>(v, {a, 15}) );
> +  VERIFY( it == v.begin() + 5 );
> +
> +#ifdef __cpp_exceptions
> +#ifdef __cpp_lib_constexpr_exceptions
> +#error remove the consteval check
> +#endif
> +  if consteval {
> +    return;
> +  }
> +
> +  std::initializer_list<T> il
> +  = {T(0), T(1), T(2), T(3), T(4), T(5), T(6), T(7), T(8), T(9)};
> +
> +  try
> +  {
> +    v.insert(v.begin(), il);
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( eq<T>(v, {a, 15}) );
> +
> +  try
> +  {
> +    v.insert(v.begin()+5, il);
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( eq<T>(v, {a, 15}) );
> +
> +  try
> +  {
> +    v.insert(v.end(), il);
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( eq<T>(v, {a, 15}) );
> +#endif
> +}
> +
> +template<typename T>
> +constexpr void
> +test_insert_repeated()
> +{
> +  T a[]{5,5,5,5,5,6,6,6,6,6,7,7,7,7,7};
> +
> +  std::inplace_vector<T, 20> v;
> +
> +  auto it = v.insert(v.begin(), 5, T(7));
> +  VERIFY( eq<T>(v, {a+10, 5}) );
> +  VERIFY( it == v.begin() );
> +
> +  it = v.insert(v.begin(), 5, T(5));
> +  VERIFY( prefix<T>(v, {a, 5}) );
> +  VERIFY( it == v.begin() );
> +
> +  it = v.insert(v.begin() + 5, 5, T(6));
> +  VERIFY( eq<T>(v, {a, 15}) );
> +  VERIFY( it == v.begin() + 5 );
> +
> +#ifdef __cpp_exceptions
> +#ifdef __cpp_lib_constexpr_exceptions
> +#error remove the consteval check
> +#endif
> +  if consteval {
> +    return;
> +  }
> +
> +  try
> +  {
> +    v.insert(v.begin(), 10u, T(6));
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( eq<T>(v, {a, 15}) );
> +
> +  try
> +  {
> +    v.insert(v.begin()+5, 10u, T(6));
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( eq<T>(v, {a, 15}) );
> +
> +  try
> +  {
> +    v.insert(v.end(), 10u, T(6));
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( eq<T>(v, {a, 15}) );
> +#endif
> +}
> +
> +template<typename T>
> +constexpr void
> +test_inserts()
> +{
> +  using namespace __gnu_test;
> +  // TODO make test iterators consteval
> +  if !consteval {
> +    do_test_ranges<test_forward_range<int>>();
> +    do_test_ranges<test_sized_range_sized_sent<int, 
> forward_iterator_wrapper>>();
> +
> +    do_test_ranges<test_input_range<int>>();
> +    do_test_ranges<test_input_sized_range<int>>();
> +    do_test_ranges<test_sized_range_sized_sent<int, 
> input_iterator_wrapper>>();
> +
> +    do_test_ranges<test_range<int, input_iterator_wrapper_nocopy>>();
> +    do_test_ranges<test_sized_range<int, input_iterator_wrapper_nocopy>>();
> +    do_test_ranges<test_sized_range_sized_sent<int, 
> input_iterator_wrapper_nocopy>>();
> +
> +    test_insert_iterators<T, input_iterator_wrapper>();
> +    test_insert_iterators<T, forward_iterator_wrapper>();
> +    test_insert_iterators<T, random_access_iterator_wrapper>();
> +  }
> +
> +  test_insert_initializer_list<T>();
> +  test_insert_repeated<T>();
> +}
> +
> +int main()
> +{
> +  auto test_all = []{
> +    test_add_to_full<0, int>();
> +    test_add_to_full<0, X>();
> +    test_add_to_full<4, int>();
> +
> +    test_inserts<int>();
> +#ifdef __cpp_lib_constexpr_inplace_vector
> +#error uncomemnt test_inserts<X>()
> +#endif
> +    if !consteval {
> +      test_add_to_full<4, X>();
> +      test_inserts<X>();
> +    }
> +    return true;
> +  };
> +
> +  test_all();
> +  static_assert(test_all());
> +}
> diff --git 
> a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/single_insert.cc
>  
> b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/single_insert.cc
> new file mode 100644
> index 00000000000..d5e893cc7f3
> --- /dev/null
> +++ 
> b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/single_insert.cc
> @@ -0,0 +1,215 @@
> +// { dg-do run { target c++26 } }
> +
> +#include <inplace_vector>
> +
> +#include <span>
> +#include <testsuite_hooks.h>
> +
> +struct X
> +{
> +  X() = default;
> +  constexpr X(int p) : v(p) {}
> +  constexpr X(const X& o) : v(o.v) { } // not trivial
> +  constexpr X& operator=(const X& o) // not trivial
> +  { v = o.v; return *this; }
> +
> +  int v;
> +
> +  friend auto operator<=>(const X&, const X&) = default;
> +};
> +
> +template<typename T, typename V, size_t N>
> +constexpr bool
> +eq(const std::inplace_vector<V, N>& l, std::span<const T> r) {
> +  if (l.size() != r.size())
> +    return false;
> +  for (auto i = 0u; i < l.size(); ++i)
> +    if (l[i] != r[i])
> +      return false;
> +  return true;
> +};
> +
> +template<size_t N, typename T>
> +constexpr void
> +test_add_to_full()
> +{
> +  using namespace __gnu_test;
> +
> +  T a[]{1,2,3,4,5,6,7,8,9};
> +  const T c(10);
> +
> +  std::inplace_vector<T, N> v(std::from_range, std::span(a, a+N));
> +
> +  VERIFY( v.try_emplace_back(1) == nullptr );
> +  VERIFY( eq<T>(v, {a, N}) );
> +  VERIFY( v.try_push_back(T(1)) == nullptr );
> +  VERIFY( eq<T>(v, {a, N}) );
> +  VERIFY( v.try_push_back(c) == nullptr );
> +  VERIFY( eq<T>(v, {a, N}) );
> +
> +#ifdef __cpp_exceptions
> +#ifdef __cpp_lib_constexpr_exceptions
> +#error remove the consteval check
> +#endif
> +  if consteval {
> +    return;
> +  }
> +
> +  try
> +  {
> +    v.emplace_back(1);
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( eq<T>(v, {a, N}) );
> +
> +  try
> +  {
> +    v.push_back(T(1));
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( eq<T>(v, {a, N}) );
> +
> +  try
> +  {
> +    v.push_back(c);
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( eq<T>(v, {a, N}) );
> +
> +  try
> +  {
> +    v.insert(v.end(), T(1));
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( eq<T>(v, {a, N}) );
> +
> +  try
> +  {
> +    v.insert(v.begin(), c);
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( eq<T>(v, {a, N}) );
> +
> +  try
> +  {
> +    v.emplace(v.end(), c);
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( eq<T>(v, {a, N}) );
> +
> +  try
> +  {
> +    v.emplace(v.begin(), T(2));
> +    VERIFY(false);
> +  }
> +  catch (std::bad_alloc const&)
> +  {
> +  }
> +  VERIFY( eq<T>(v, {a, N}) );
> +#endif
> +}
> +
> +template<typename T>
> +constexpr void
> +test_inserts()
> +{
> +  T a[]{3,14,13,1,2,3,4,5,3,7,8,3,10,11,3};
> +  const T c(3);
> +
> +  std::inplace_vector<T, 20> v;
> +
> +  v.emplace_back(1);
> +  VERIFY( eq<T>(v, {a+3, 1}) );
> +  v.push_back(T(2));
> +  VERIFY( eq<T>(v, {a+3, 2}) );
> +  v.push_back(c);
> +  VERIFY( eq<T>(v, {a+3, 3}) );
> +
> +  v.unchecked_emplace_back(4);
> +  VERIFY( eq<T>(v, {a+3, 4}) );
> +  v.unchecked_push_back(T(5));
> +  VERIFY( eq<T>(v, {a+3, 5}) );
> +  v.unchecked_push_back(c);
> +  VERIFY( eq<T>(v, {a+3, 6}) );
> +
> +  T* ptr = v.try_emplace_back(7);
> +  VERIFY( eq<T>(v, {a+3, 7}) );
> +  VERIFY( ptr = &v.back() );
> +  ptr = v.try_push_back(T(8));
> +  VERIFY( eq<T>(v, {a+3, 8}) );
> +  VERIFY( ptr = &v.back() );
> +  ptr = v.try_push_back(c);
> +  VERIFY( eq<T>(v, {a+3, 9}) );
> +  VERIFY( ptr = &v.back() );
> +
> +  auto it = v.emplace(v.end(), 10);
> +  VERIFY( eq<T>(v, {a+3, 10}) );
> +  VERIFY( it == v.end()-1 );
> +  it = v.insert(v.end(), T(11));
> +  VERIFY( eq<T>(v, {a+3, 11}) );
> +  VERIFY( it == v.end()-1 );
> +  it = v.insert(v.end(), c);
> +  VERIFY( eq<T>(v, {a+3, 12}) );
> +  VERIFY( it == v.end()-1 );
> +
> +  it = v.emplace(v.begin(), 13);
> +  VERIFY( eq<T>(v, {a+2, 13}) );
> +  VERIFY( it == v.begin() );
> +  it = v.insert(v.begin(), T(14));
> +  VERIFY( eq<T>(v, {a+1, 14}) );
> +  VERIFY( it == v.begin() );
> +  it = v.insert(v.begin(), c);
> +  VERIFY( eq<T>(v, {a+0, 15}) );
> +  VERIFY( it == v.begin() );
> +
> +  it = v.emplace(v.begin()+2, 22);
> +  VERIFY( *it == 22 );
> +  VERIFY( it == v.begin()+2 );
> +  it = v.insert(v.begin()+6, T(24));
> +  VERIFY( *it == 24 );
> +  VERIFY( it == v.begin()+6 );
> +  it = v.insert(v.begin()+13, c);
> +  VERIFY( *it == 3 );
> +  VERIFY( it == v.begin()+13 );
> +}
> +
> +int main()
> +{
> +  auto test_all = [] {
> +    test_add_to_full<0, int>();
> +    test_add_to_full<0, X>();
> +
> +    test_add_to_full<4, int>();
> +
> +    test_inserts<int>();
> +#ifdef __cpp_lib_constexpr_inplace_vector
> +#error uncomemnt test_inserts<X>()
> +#endif
> +    if ! consteval {
> +      test_add_to_full<4, X>();
> +      test_inserts<X>();
> +    }
> +    return true;
> +  };
> +
> +  test_all();
> +  static_assert(test_all());;
> +}
> diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/move.cc 
> b/libstdc++-v3/testsuite/23_containers/inplace_vector/move.cc
> new file mode 100644
> index 00000000000..5abcc8764bd
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/move.cc
> @@ -0,0 +1,358 @@
> +// { dg-do run { target c++26 } }
> +
> +#include <inplace_vector>
> +#include <ranges>
> +#include <testsuite_hooks.h>
> +
> +struct X
> +{
> +  X() = default;
> +  constexpr X(int p) : v(p) {}
> +  constexpr X(const X& o) : v(o.v) { } // not trivial
> +  constexpr X(X&& o) : v(o.v) { } // not trivial
> +
> +  constexpr X& operator=(const X& o) // not trivial
> +  { v = o.v; return *this; }
> +  constexpr X& operator=(X&& o) // not trivial
> +  { v = o.v; return *this; }
> +
> +  int v;
> +
> +  friend auto operator<=>(const X&, const X&) = default;
> +};
> +
> +template<bool CNoex, bool ANoex>
> +struct N
> +{
> +  N() = default;
> +  constexpr N(N&&) noexcept(CNoex) { } // not trivial
> +  constexpr N& operator=(N&& o) noexcept(ANoex) // not trivial
> +  { return *this; }
> +};
> +
> +struct D
> +{
> +  D() = default;
> +  D(D&&) = default;
> +  D& operator=(D&&) = default;
> +  ~D() {} // not trivially destructible
> +};
> +
> +struct U
> +{
> +  U() = default;
> +  U(U&&) noexcept(false) = default; // lies about noexcept, is trivial but 
> throwing
> +  U& operator=(U&&) noexcept(false) = default; // lies about noexcept, is 
> trivial but throwing
> +};
> +
> +template<bool SNoex, bool CNoex, bool ANoex>
> +struct S {
> +  S() = default;
> +  constexpr S(S&&) noexcept(CNoex) { } // not trivial
> +  constexpr S& operator=(S&& o) noexcept(ANoex) // not trivial
> +  { return *this; }
> +
> +  friend constexpr
> +  void swap(S&, S&) noexcept(SNoex) {}
> +};
> +
> +// n5008 inplace.vector.overview says for inplace_vector<T, 0>
> +// provides trivial copy/move/default cosntructpr regardless of T
> +struct Z
> +{
> +  Z(const Z&) = delete;
> +  Z& operator=(const Z&) = delete;
> +};
> +
> +template<size_t N, typename T>
> +  constexpr std::inplace_vector<T, N>
> +  materialize(std::initializer_list<int> il)
> +  { 
> +    std::inplace_vector<T, N> res;
> +    for (int x : il)
> +      res.emplace_back(x);
> +    return res;
> +  }
> +
> +static_assert(std::is_move_constructible_v<std::inplace_vector<int, 2>>);
> +static_assert(std::is_move_constructible_v<std::inplace_vector<X, 2>>);
> +static_assert(std::is_move_constructible_v<std::inplace_vector<N<false, 
> false>, 2>>);
> +static_assert(std::is_move_constructible_v<std::inplace_vector<D, 2>>);
> +static_assert(std::is_move_constructible_v<std::inplace_vector<U, 2>>);
> +// The operators are not constrained, as for any other container
> +static_assert(std::is_move_constructible_v<std::inplace_vector<Z, 2>>);
> +
> +static_assert(std::is_nothrow_move_constructible_v<std::inplace_vector<int, 
> 2>>);
> +static_assert(!std::is_nothrow_move_constructible_v<std::inplace_vector<X, 
> 2>>);
> +static_assert(std::is_nothrow_move_constructible_v<std::inplace_vector<N<true,
>  true>, 2>>);
> +static_assert(std::is_nothrow_move_constructible_v<std::inplace_vector<N<true,
>  false>, 2>>);
> +static_assert(!std::is_nothrow_move_constructible_v<std::inplace_vector<N<false,
>  true>, 2>>);
> +static_assert(!std::is_nothrow_move_constructible_v<std::inplace_vector<N<false,
>  false>, 2>>);
> +static_assert(std::is_nothrow_move_constructible_v<std::inplace_vector<D, 
> 2>>);
> +static_assert(!std::is_nothrow_move_constructible_v<std::inplace_vector<U, 
> 2>>);
> +
> +static_assert(std::is_trivially_move_constructible_v<std::inplace_vector<int,
>  2>>);
> +static_assert(!std::is_trivially_move_constructible_v<std::inplace_vector<X, 
> 2>>);
> +static_assert(!std::is_trivially_move_constructible_v<std::inplace_vector<N<true,
>  true>, 2>>);
> +// is_trivially_move_constructible_v checks destructor
> +static_assert(!std::is_trivially_move_constructible_v<std::inplace_vector<D, 
> 2>>);
> +static_assert(std::is_trivially_move_constructible_v<std::inplace_vector<U, 
> 2>>);
> +
> +static_assert(std::is_move_assignable_v<std::inplace_vector<int, 2>>);
> +static_assert(std::is_move_assignable_v<std::inplace_vector<X, 2>>);
> +static_assert(std::is_move_assignable_v<std::inplace_vector<N<false, false>, 
> 2>>);
> +static_assert(std::is_move_assignable_v<std::inplace_vector<D, 2>>);
> +static_assert(std::is_move_assignable_v<std::inplace_vector<U, 2>>);
> +// The operators are not constrained, as for any other container
> +static_assert(std::is_move_assignable_v<std::inplace_vector<Z, 2>>);
> +
> +static_assert(std::is_nothrow_move_assignable_v<std::inplace_vector<int, 
> 2>>);
> +static_assert(!std::is_nothrow_move_assignable_v<std::inplace_vector<X, 2>>);
> +static_assert(std::is_nothrow_move_assignable_v<std::inplace_vector<N<true, 
> true>, 2>>);
> +static_assert(!std::is_nothrow_move_assignable_v<std::inplace_vector<N<true, 
> false>, 2>>);
> +static_assert(!std::is_nothrow_move_assignable_v<std::inplace_vector<N<false,
>  true>, 2>>);
> +static_assert(!std::is_nothrow_move_assignable_v<std::inplace_vector<N<false,
>  false>, 2>>);
> +static_assert(std::is_nothrow_move_assignable_v<std::inplace_vector<D, 2>>);
> +static_assert(!std::is_nothrow_move_assignable_v<std::inplace_vector<U, 2>>);
> +
> +static_assert(std::is_trivially_move_assignable_v<std::inplace_vector<int, 
> 2>>);
> +static_assert(!std::is_trivially_move_assignable_v<std::inplace_vector<X, 
> 2>>);
> +static_assert(!std::is_trivially_move_assignable_v<std::inplace_vector<N<true,
>  true>, 2>>);
> +// destructor is not trivial
> +static_assert(!std::is_trivially_move_assignable_v<std::inplace_vector<D, 
> 2>>);
> +static_assert(std::is_trivially_move_assignable_v<std::inplace_vector<U, 
> 2>>);
> +
> +static_assert(std::is_nothrow_swappable_v<std::inplace_vector<int, 2>>);
> +static_assert(!std::is_nothrow_swappable_v<std::inplace_vector<X, 2>>);
> +static_assert(std::is_nothrow_swappable_v<std::inplace_vector<N<true, true>, 
> 2>>);
> +static_assert(!std::is_nothrow_swappable_v<std::inplace_vector<N<true, 
> false>, 2>>);
> +static_assert(!std::is_nothrow_swappable_v<std::inplace_vector<N<false, 
> true>, 2>>);
> +static_assert(!std::is_nothrow_swappable_v<std::inplace_vector<N<false, 
> false>, 2>>);
> +static_assert(std::is_nothrow_swappable_v<std::inplace_vector<S<true, true, 
> true>, 2>>);
> +static_assert(std::is_nothrow_swappable_v<std::inplace_vector<S<true, true, 
> false>, 2>>);
> +static_assert(!std::is_nothrow_swappable_v<std::inplace_vector<S<true, 
> false, true>, 2>>);
> +static_assert(!std::is_nothrow_swappable_v<std::inplace_vector<S<true, 
> false, false>, 2>>);
> +static_assert(!std::is_nothrow_swappable_v<std::inplace_vector<S<false, 
> true, false>, 2>>);
> +static_assert(!std::is_nothrow_swappable_v<std::inplace_vector<S<false, 
> false, false>, 2>>);
> +static_assert(std::is_nothrow_swappable_v<std::inplace_vector<D, 2>>);
> +static_assert(!std::is_nothrow_swappable_v<std::inplace_vector<U, 2>>);
> +
> +static_assert(std::is_nothrow_move_constructible_v<std::inplace_vector<int, 
> 0>>);
> +static_assert(std::is_nothrow_move_constructible_v<std::inplace_vector<X, 
> 0>>);
> +static_assert(std::is_nothrow_move_constructible_v<std::inplace_vector<N<false,
>  false>, 0>>);
> +static_assert(std::is_nothrow_move_constructible_v<std::inplace_vector<D, 
> 0>>);
> +static_assert(std::is_nothrow_move_constructible_v<std::inplace_vector<U, 
> 0>>);
> +static_assert(std::is_nothrow_move_constructible_v<std::inplace_vector<Z, 
> 0>>);
> +
> +static_assert(std::is_trivially_move_constructible_v<std::inplace_vector<int,
>  0>>);
> +static_assert(std::is_trivially_move_constructible_v<std::inplace_vector<X, 
> 0>>);
> +static_assert(std::is_trivially_move_constructible_v<std::inplace_vector<D, 
> 0>>);
> +static_assert(std::is_trivially_move_constructible_v<std::inplace_vector<U, 
> 0>>);
> +static_assert(std::is_trivially_move_constructible_v<std::inplace_vector<Z, 
> 0>>);
> +
> +static_assert(std::is_nothrow_move_assignable_v<std::inplace_vector<int, 
> 0>>);
> +static_assert(std::is_nothrow_move_assignable_v<std::inplace_vector<X, 0>>);
> +static_assert(std::is_nothrow_move_assignable_v<std::inplace_vector<N<false, 
> false>, 0>>);
> +static_assert(std::is_nothrow_move_assignable_v<std::inplace_vector<D, 0>>);
> +static_assert(std::is_nothrow_move_assignable_v<std::inplace_vector<U, 0>>);
> +static_assert(std::is_nothrow_move_assignable_v<std::inplace_vector<Z, 0>>);
> +
> +static_assert(std::is_trivially_move_assignable_v<std::inplace_vector<int, 
> 0>>);
> +static_assert(std::is_trivially_move_assignable_v<std::inplace_vector<X, 
> 0>>);
> +static_assert(std::is_trivially_move_assignable_v<std::inplace_vector<N<false,
>  false>, 0>>);
> +static_assert(std::is_trivially_move_assignable_v<std::inplace_vector<D, 
> 0>>);
> +static_assert(std::is_trivially_move_assignable_v<std::inplace_vector<U, 
> 0>>);
> +static_assert(std::is_trivially_move_assignable_v<std::inplace_vector<Z, 
> 0>>);
> +
> +static_assert(std::is_nothrow_swappable_v<std::inplace_vector<int, 0>>);
> +static_assert(std::is_nothrow_swappable_v<std::inplace_vector<X, 0>>);
> +static_assert(std::is_nothrow_swappable_v<std::inplace_vector<N<false, 
> false>, 0>>);
> +static_assert(std::is_nothrow_swappable_v<std::inplace_vector<D, 0>>);
> +static_assert(std::is_nothrow_swappable_v<std::inplace_vector<U, 0>>);
> +static_assert(std::is_nothrow_swappable_v<std::inplace_vector<Z, 0>>);
> +
> +template<typename T, size_t N>
> +constexpr bool
> +eq(const std::inplace_vector<T, N>& s, std::span<const T> o)
> +{ return std::ranges::equal(s, o); }
> +
> +constexpr void
> +test_ctor()
> +{
> +  auto e0 = materialize<0, int>({});
> +  VERIFY( e0.empty() );
> +  auto e1 = materialize<0, X>({});
> +  VERIFY( e1.empty() );
> +  auto e2 = materialize<0, Z>({});
> +  VERIFY( e2.empty() );
> +
> +  auto c0 = materialize<5, int>({});
> +  VERIFY( c0.empty() );
> +
> +  auto c3 = materialize<5, int>({1, 2, 3});
> +  VERIFY( eq(c3, {1, 2, 3}) );
> +
> +  auto c5 = materialize<5, int>({1, 2, 3, 4, 5});
> +  VERIFY( eq(c5, {1, 2, 3, 4, 5}) );
> +
> +#ifdef __cpp_lib_constexpr_inplace_vector
> +#error remove the consteval check
> +#endif
> +  if consteval {
> +    return;
> +  }
> +
> +  auto x0 = materialize<3, X>({});
> +  VERIFY( x0.empty() );
> +
> +  auto x2 = materialize<3, X>({1, 2});
> +  VERIFY( eq(x2, {1, 2}) );
> +
> +  auto x3 = materialize<3, X>({1, 2, 3});
> +  VERIFY( eq(x3, {1, 2, 3}) );
> +}
> +
> +constexpr void
> +test_assign()
> +{
> +  std::inplace_vector<int, 0> e0;
> +  e0 = materialize<0, int>({});
> +  VERIFY( e0.empty() );
> +  std::inplace_vector<X, 0> e1;
> +  e1 = materialize<0, X>({});
> +  VERIFY( e1.empty() );
> +  std::inplace_vector<Z, 0> e2;
> +  e2 = materialize<0, Z>({});
> +  VERIFY( e2.empty() );
> +
> +  std::inplace_vector<int, 5> c;
> +  c = materialize<5, int>({});
> +  VERIFY( c.empty() );
> +
> +  c = materialize<5, int>({1, 2, 3});
> +  VERIFY( eq(c, {1, 2, 3}) );
> + 
> +  c = materialize<5, int>({1, 2, 3, 4, 5});
> +  VERIFY( eq(c, {1, 2, 3, 4, 5}) );
> +
> +  c = materialize<5, int>({4, 5});
> +  VERIFY( eq(c, {4, 5}) );
> +
> +  c = materialize<5, int>({});
> +  VERIFY( c.empty() );
> +
> +#ifdef __cpp_lib_constexpr_inplace_vector
> +#error remove the consteval check
> +#endif
> +  if consteval {
> +    return;
> +  }
> +
> +  std::inplace_vector<X, 5> x;
> +  x = materialize<5, X>({});
> +  VERIFY( x.empty() );
> +
> +  x = materialize<5, X>({1, 2, 3});
> +  VERIFY( eq(x, {1, 2, 3}) );
> + 
> +  x = materialize<5, X>({1, 2, 3, 4, 5});
> +  VERIFY( eq(x, {1, 2, 3, 4, 5}) );
> +
> +  x = materialize<5, X>({4, 5});
> +  VERIFY( eq(x, {4, 5}) );
> +
> +  x = materialize<5, X>({});
> +  VERIFY( x.empty() );
> +}
> +
> +constexpr void
> +test_swap()
> +{
> +  std::inplace_vector<int, 0> e0a, e0b;
> +  swap(e0a, e0b);
> +  VERIFY( e0a.empty() );
> +  VERIFY( e0b.empty() );
> +  e0a.swap(e0b);
> +  VERIFY( e0a.empty() );
> +  VERIFY( e0b.empty() );
> + 
> +  std::inplace_vector<X, 0> e1a, e1b;
> +  swap(e1a, e1b);
> +  VERIFY( e1a.empty() );
> +  VERIFY( e1b.empty() );
> +  e1a.swap(e1b);
> +  VERIFY( e1a.empty() );
> +  VERIFY( e1b.empty() );
> +
> +  std::inplace_vector<Z, 0> e2a, e2b;
> +  swap(e2a, e2b);
> +  VERIFY( e2a.empty() );
> +  VERIFY( e2b.empty() );
> +  e2a.swap(e2b);
> +  VERIFY( e2a.empty() );
> +  VERIFY( e2b.empty() );
> +
> +  std::inplace_vector<int, 5> c0;
> +  std::inplace_vector<int, 5> c3{1, 2, 3};
> +  std::inplace_vector<int, 5> c5{1, 2, 3, 4, 5};
> +
> +  swap(c0, c3);
> +  VERIFY( c3.empty() );
> +  VERIFY( eq(c0, {1, 2, 3}) );
> +  c0.swap(c3);
> +  VERIFY( c0.empty() );
> +  VERIFY( eq(c3, {1, 2, 3}) );
> +
> +  swap(c3, c5);
> +  VERIFY( eq(c5, {1, 2, 3}) );
> +  VERIFY( eq(c3, {1, 2, 3, 4, 5}) );
> +  c5.swap(c3);
> +  VERIFY( eq(c3, {1, 2, 3}) );
> +  VERIFY( eq(c5, {1, 2, 3, 4, 5}) );
> +
> +#ifdef __cpp_lib_constexpr_inplace_vector
> +#error remove the consteval check
> +#endif
> +  if consteval {
> +    return;
> +  }
> +
> +  std::inplace_vector<X, 5> x0;
> +  std::inplace_vector<X, 5> x3 = {1, 2, 3};
> +  std::inplace_vector<X, 5> x5 = {1, 2, 3, 4, 5};
> +
> +  swap(x0, x3);
> +  VERIFY( x3.empty() );
> +  VERIFY( eq(x0, {1, 2, 3}) );
> +  x0.swap(x3);
> +  VERIFY( x0.empty() );
> +  VERIFY( eq(x3, {1, 2, 3}) );
> +
> +  swap(x3, x5);
> +  VERIFY( eq(x5, {1, 2, 3}) );
> +  VERIFY( eq(x3, {1, 2, 3, 4, 5}) );
> +  x5.swap(x3);
> +  VERIFY( eq(x3, {1, 2, 3}) );
> +  VERIFY( eq(x5, {1, 2, 3, 4, 5}) );
> +}
> +
> +constexpr auto e0 = materialize<0, int>({});
> +constexpr auto e1 = materialize<0, X>({});
> +constexpr auto e2 = materialize<0, Z>({});
> +
> +constexpr auto t1 = materialize<3, int>({});
> +constexpr auto t2 = materialize<3, int>({1, 2});
> +constexpr auto t3 = materialize<3, int>({11, 22, 33});
> +
> +int main()
> +{
> +  auto tests = [] {
> +    test_ctor();
> +    test_assign();
> +    test_swap();
> +    return true;
> +  };
> +
> +  tests();
> +  constexpr bool _ = tests();
> +}
> diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/relops.cc 
> b/libstdc++-v3/testsuite/23_containers/inplace_vector/relops.cc
> new file mode 100644
> index 00000000000..f9c5ce96ae1
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/relops.cc
> @@ -0,0 +1,60 @@
> +// { dg-do run { target c++26 } }
> +
> +#include <inplace_vector>
> +
> +#include <span>
> +#include <testsuite_hooks.h>
> +
> +template<size_t N, typename T>
> +constexpr void
> +test_equal(size_t c)
> +{
> +  T a[]{1, 2, 3, 4, 5, 6, 7, 8, 9};
> +  std::inplace_vector<T, N> v(a, a+c);
> +  VERIFY(   v == v  );
> +  VERIFY( !(v != v) );
> +  VERIFY( !(v <  v) );
> +  VERIFY( !(v >  v) );
> +  VERIFY(   v <= v  );
> +  VERIFY(   v >= v  );
> +  VERIFY( (v <=> v) == 0 );
> +}
> +
> +template<typename T>
> +constexpr void
> +test_not_equal()
> +{
> +  std::inplace_vector<T, 10> v3l{T{1}, T{2}, T{3}};
> +  std::inplace_vector<T, 10> v3g{T{1}, T{3}, T{3}};
> +  VERIFY( !(v3l == v3g) );
> +  VERIFY(   v3l != v3g  );
> +  VERIFY(   v3l <  v3g  );
> +  VERIFY( !(v3l >  v3g) );
> +  VERIFY(   v3l <= v3g  );
> +  VERIFY( !(v3l >= v3g) );
> +  VERIFY( (v3l <=> v3g) < 0 );
> +
> +  std::inplace_vector<T, 10> v2{T{1}, T{2}};
> +  VERIFY( !(v2 == v3l) );
> +  VERIFY(   v2 != v3l  );
> +  VERIFY(   v2 <  v3l  );
> +  VERIFY( !(v2 >  v3l) );
> +  VERIFY(   v2 <= v3l  );
> +  VERIFY( !(v2 >= v3l) );
> +  VERIFY( (v2 <=> v3l) < 0 );
> +}
> +
> +int main()
> +{
> +  auto test_all = [] {
> +    test_equal<0, int>(0);
> +    test_equal<4, int>(0);
> +    test_equal<4, int>(2);
> +    test_equal<4, int>(4);
> +    test_not_equal<int>();
> +    return true;
> +  };
> +
> +  test_all();
> +  static_assert(test_all());;
> +}
> diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/version.cc 
> b/libstdc++-v3/testsuite/23_containers/inplace_vector/version.cc
> new file mode 100644
> index 00000000000..a5bbdb8464b
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/version.cc
> @@ -0,0 +1,20 @@
> +// { dg-do preprocess { target c++26 } }
> +// { dg-add-options no_pch }
> +
> +#include <inplace_vector>
> +
> +#ifndef __cpp_lib_inplace_vector
> +# error "Feature-test macro for inplace_vector missing in <inplace_vector>"
> +#elif __cpp_lib_inplace_vector != 202406L
> +# error "Feature-test macro for inplace_vector has wrong value in 
> <inplace_vector>"
> +#endif
> +
> +#undef __cpp_lib_inplace_vector
> +
> +#include <version>
> +
> +#ifndef __cpp_lib_inplace_vector
> +# error "Feature-test macro for inplace_vector missing in <version>"
> +#elif __cpp_lib_inplace_vector != 202406L
> +# error "Feature-test macro for inplace_vector has wrong value in <version>"
> +#endif
> diff --git a/libstdc++-v3/testsuite/util/testsuite_iterators.h 
> b/libstdc++-v3/testsuite/util/testsuite_iterators.h
> index 74a87395cd7..e9f8f56eb27 100644
> --- a/libstdc++-v3/testsuite/util/testsuite_iterators.h
> +++ b/libstdc++-v3/testsuite/util/testsuite_iterators.h
> @@ -270,6 +270,12 @@ namespace __gnu_test
>        return !(*this == in);
>      }
>  
> +    T*
> +    base() const
> +    {
> +      return ptr;
> +    }
> +
>      T&
>      operator*() const
>      {
> -- 
> 2.49.0
> 
> 

Reply via email to