[libcxx-commits] [libcxx] [libc++] Implement P0843R14: `inplace_vector` (PR #204008)

A. Jiang via libcxx-commits libcxx-commits at lists.llvm.org
Mon Jun 15 18:56:26 PDT 2026


================
@@ -0,0 +1,1132 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_INPLACE_VECTOR
+#define _LIBCPP_INPLACE_VECTOR
+
+/*
+    inplace_vector synopsis
+
+namespace std {
+  template<class T, size_t N>
+  class inplace_vector {
+  public:
+    // types:
+    using value_type             = T;
+    using pointer                = T*;
+    using const_pointer          = const T*;
+    using reference              = value_type&;
+    using const_reference        = const value_type&;
+    using size_type              = size_t;
+    using difference_type        = ptrdiff_t;
+    using iterator               = implementation-defined; // see [container.requirements]
+    using const_iterator         = implementation-defined; // see [container.requirements]
+    using reverse_iterator       = std::reverse_iterator<iterator>;
+    using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+    // [inplace.vector.cons], construct/copy/destroy
+    constexpr inplace_vector() noexcept;
+    constexpr explicit inplace_vector(size_type n);                         // freestanding-deleted
+    constexpr inplace_vector(size_type n, const T& value);                  // freestanding-deleted
+    template<class InputIterator>
+      constexpr inplace_vector(InputIterator first, InputIterator last);    // freestanding-deleted
+    template<container-compatible-range<T> R>
+      constexpr inplace_vector(from_range_t, R&& rg);                       // freestanding-deleted
+    constexpr inplace_vector(const inplace_vector&);
+    constexpr inplace_vector(inplace_vector&&)
+      noexcept(N == 0 || is_nothrow_move_constructible_v<T>);
+    constexpr inplace_vector(initializer_list<T> il);                       // freestanding-deleted
+    constexpr ~inplace_vector();
+    constexpr inplace_vector& operator=(const inplace_vector& other);
+    constexpr inplace_vector& operator=(inplace_vector&& other)
+      noexcept(N == 0 || (is_nothrow_move_assignable_v<T> &&
+                          is_nothrow_move_constructible_v<T>));
+    constexpr inplace_vector& operator=(initializer_list<T>);               // freestanding-deleted
+    template<class InputIterator>
+      constexpr void assign(InputIterator first, InputIterator last);       // freestanding-deleted
+    template<container-compatible-range<T> R>
+      constexpr void assign_range(R&& rg);                                  // freestanding-deleted
+    constexpr void assign(size_type n, const T& u);                         // freestanding-deleted
+    constexpr void assign(initializer_list<T> il);                          // freestanding-deleted
+
+    // iterators
+    constexpr iterator               begin()         noexcept;
+    constexpr const_iterator         begin()   const noexcept;
+    constexpr iterator               end()           noexcept;
+    constexpr const_iterator         end()     const noexcept;
+    constexpr reverse_iterator       rbegin()        noexcept;
+    constexpr const_reverse_iterator rbegin()  const noexcept;
+    constexpr reverse_iterator       rend()          noexcept;
+    constexpr const_reverse_iterator rend()    const noexcept;
+
+    constexpr const_iterator         cbegin()  const noexcept;
+    constexpr const_iterator         cend()    const noexcept;
+    constexpr const_reverse_iterator crbegin() const noexcept;
+    constexpr const_reverse_iterator crend()   const noexcept;
+
+    // [inplace.vector.capacity], capacity
+    constexpr bool empty() const noexcept;
+    constexpr size_type size() const noexcept;
+    static constexpr size_type max_size() noexcept;
+    static constexpr size_type capacity() noexcept;
+    constexpr void resize(size_type sz);                                    // freestanding-deleted
+    constexpr void resize(size_type sz, const T& c);                        // freestanding-deleted
+    static constexpr void reserve(size_type n);                             // freestanding-deleted
+    static constexpr void shrink_to_fit() noexcept;
+
+    // element access
+    constexpr reference       operator[](size_type n);
+    constexpr const_reference operator[](size_type n) const;
+    constexpr reference       at(size_type n);                              // freestanding-deleted
+    constexpr const_reference at(size_type n) const;                        // freestanding-deleted
+    constexpr reference       front();
+    constexpr const_reference front() const;
+    constexpr reference       back();
+    constexpr const_reference back() const;
+
+    // [inplace.vector.data], data access
+    constexpr       T* data()       noexcept;
+    constexpr const T* data() const noexcept;
+
+    // [inplace.vector.modifiers], modifiers
+    template<class... Args>
+      constexpr reference emplace_back(Args&&... args);                     // freestanding-deleted
+    constexpr reference push_back(const T& x);                              // freestanding-deleted
+    constexpr reference push_back(T&& x);                                   // freestanding-deleted
+    template<container-compatible-range<T> R>
+      constexpr void append_range(R&& rg);                                  // freestanding-deleted
+    constexpr void pop_back();
+
+    template<class... Args>
+      constexpr optional<reference> try_emplace_back(Args&&... args);
+    constexpr optional<reference> try_push_back(const T& x);
+    constexpr optional<reference> try_push_back(T&& x);
+
+    template<class... Args>
+      constexpr reference unchecked_emplace_back(Args&&... args);
+    constexpr reference unchecked_push_back(const T& x);
+    constexpr reference unchecked_push_back(T&& x);
+
+    template<class... Args>
+      constexpr iterator emplace(const_iterator position, Args&&... args);  // freestanding-deleted
+    constexpr iterator insert(const_iterator position, const T& x);         // freestanding-deleted
+    constexpr iterator insert(const_iterator position, T&& x);              // freestanding-deleted
+    constexpr iterator insert(const_iterator position, size_type n,         // freestanding-deleted
+                              const T& x);
+    template<class InputIterator>
+      constexpr iterator insert(const_iterator position,                    // freestanding-deleted
+                                InputIterator first, InputIterator last);
+    template<container-compatible-range<T> R>
+      constexpr iterator insert_range(const_iterator position, R&& rg);     // freestanding-deleted
+    constexpr iterator insert(const_iterator position,                      // freestanding-deleted
+                              initializer_list<T> il);
+    constexpr iterator erase(const_iterator position);
+    constexpr iterator erase(const_iterator first, const_iterator last);
+    constexpr void swap(inplace_vector& x)
+      noexcept(N == 0 || (is_nothrow_swappable_v<T> &&
+                          is_nothrow_move_constructible_v<T>));
+    constexpr void clear() noexcept;
+
+    friend constexpr bool operator==(const inplace_vector& x,
+                                     const inplace_vector& y);
+    friend constexpr auto
+      operator<=>(const inplace_vector& x, const inplace_vector& y)
+        requires requires (const T t) { synth-three-way(t, t); }
+      {
+        return lexicographical_compare_three_way(x.begin(), x.end(), y.begin(), y.end(),
+                                                 synth-three-way);
+      }
+    friend constexpr void swap(inplace_vector& x, inplace_vector& y)
+      noexcept(N == 0 || (is_nothrow_swappable_v<T> &&
+                          is_nothrow_move_constructible_v<T>))
+      { x.swap(y); }
+  };
+}
+*/
+
+#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
+#  include <__cxx03/__config>
+#else
+#  include <__config>
+
+#  if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#    pragma GCC system_header
+#  endif
+
+_LIBCPP_PUSH_MACROS
+#  include <__undef_macros>
+
+#  if _LIBCPP_STD_VER >= 26
+#    include <__algorithm/fill_n.h>
+#    include <__algorithm/lexicographical_compare_three_way.h>
+#    include <__algorithm/min.h>
+#    include <__algorithm/move.h>
+#    include <__algorithm/move_backward.h>
+#    include <__algorithm/ranges_copy.h>
+#    include <__algorithm/ranges_copy_n.h>
+#    include <__algorithm/remove.h>
+#    include <__algorithm/remove_if.h>
+#    include <__algorithm/rotate.h>
+#    include <__algorithm/swap_ranges.h>
+#    include <__compare/synth_three_way.h>
+#    include <__compare/three_way_comparable.h>
+#    include <__concepts/assignable.h>
+#    include <__cstddef/ptrdiff_t.h>
+#    include <__cstddef/size_t.h>
+#    include <__iterator/bounded_iter.h>
+#    include <__iterator/capacity_aware_iterator.h>
+#    include <__iterator/concepts.h>
+#    include <__iterator/distance.h>
+#    include <__iterator/iterator_traits.h>
+#    include <__iterator/move_iterator.h>
+#    include <__iterator/reverse_iterator.h>
+#    include <__memory/construct_at.h>
+#    include <__memory/destroy.h>
+#    include <__memory/ranges_destroy.h>
+#    include <__memory/ranges_uninitialized_algorithms.h>
+#    include <__memory/uninitialized_algorithms.h>
+#    include <__new/exceptions.h>
+#    include <__ranges/access.h>
+#    include <__ranges/concepts.h>
+#    include <__ranges/container_compatible_range.h>
+#    include <__ranges/from_range.h>
+#    include <__type_traits/is_nothrow_constructible.h>
+#    include <__type_traits/is_swappable.h>
+#    include <__type_traits/is_trivially_assignable.h>
+#    include <__type_traits/is_trivially_constructible.h>
+#    include <__type_traits/is_trivially_copyable.h>
+#    include <__type_traits/is_trivially_destructible.h>
+#    include <__utility/exception_guard.h>
+#    include <__utility/move.h>
+#    include <__utility/unreachable.h>
+#    include <__verbose_trap>
+#    include <initializer_list>
+#    include <limits>
+#    include <optional>
+#    include <stdexcept>
+#    include <version>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+template <class _Tp, size_t _Cap>
+class inplace_vector {
+private:
+  static constexpr decltype(auto) __get_size_type() {
+    if constexpr (_Cap <= std::numeric_limits<unsigned char>::max() && sizeof(unsigned char) < sizeof(std::size_t))
+      return static_cast<unsigned char>(0);
+    else if constexpr (_Cap <= std::numeric_limits<unsigned short>::max() &&
+                       sizeof(unsigned short) < sizeof(std::size_t))
+      return static_cast<unsigned short>(0);
+    else if constexpr (_Cap <= std::numeric_limits<unsigned int>::max() && sizeof(unsigned int) < sizeof(std::size_t))
+      return static_cast<unsigned int>(0);
+    else if constexpr (_Cap <= std::numeric_limits<unsigned long>::max() && sizeof(unsigned long) < sizeof(std::size_t))
+      return static_cast<unsigned long>(0);
+    else
+      return static_cast<std::size_t>(0);
+  }
+
+  using __size_type = decltype(__get_size_type());
----------------
frederick-vs-ja wrote:

Internal typedef-names (including alias templates) should be marked `_LIBCPP_NODEBUG`, unless the typedef-name is function-local.
```suggestion
  using __size_type _LIBCPP_NODEBUG = decltype(__get_size_type());
```

https://github.com/llvm/llvm-project/pull/204008


More information about the libcxx-commits mailing list