[libcxx-commits] [libcxx] [libc++] Implement `std::inplace_vector<T, N>` (PR #105981)
Mital Ashok via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Sep 17 03:31:27 PDT 2024
https://github.com/MitalAshok updated https://github.com/llvm/llvm-project/pull/105981
>From 1a71bbff98913a5cafbc7e853ea274193e6867c1 Mon Sep 17 00:00:00 2001
From: Mital Ashok <mital at mitalashok.co.uk>
Date: Fri, 30 Aug 2024 15:03:13 +0100
Subject: [PATCH] [libc++] Implement `std::inplace_vector<T, N>`
---
libcxx/docs/FeatureTestMacroTable.rst | 2 +-
libcxx/docs/Status/Cxx2cPapers.csv | 2 +-
libcxx/include/CMakeLists.txt | 1 +
libcxx/include/__configuration/abi.h | 3 +-
libcxx/include/__iterator/wrap_iter.h | 4 +
libcxx/include/__std_clang_module | 1 +
libcxx/include/inplace_vector | 1091 +++++++++++++++++
libcxx/include/module.modulemap | 4 +
libcxx/include/version | 2 +-
libcxx/modules/std.compat.cppm.in | 3 -
libcxx/modules/std.cppm.in | 4 +-
.../test/libcxx/transitive_includes/cxx03.csv | 17 +
.../test/libcxx/transitive_includes/cxx11.csv | 17 +
.../test/libcxx/transitive_includes/cxx14.csv | 17 +
.../test/libcxx/transitive_includes/cxx17.csv | 17 +
.../test/libcxx/transitive_includes/cxx20.csv | 17 +
.../test/libcxx/transitive_includes/cxx23.csv | 11 +
.../test/libcxx/transitive_includes/cxx26.csv | 11 +
.../sequences/inplace.vector/access.pass.cpp | 148 +++
.../sequences/inplace.vector/compare.pass.cpp | 131 ++
.../inplace.vector/compare.three_way.pass.cpp | 38 +
.../constant_initialization.pass.cpp | 75 ++
.../inplace.vector/contiguous.pass.cpp | 49 +
.../inplace.vector/empy_type.compile.pass.cpp | 33 +
.../inplace.vector.capacity/capacity.pass.cpp | 52 +
.../inplace.vector.capacity/empty.pass.cpp | 67 +
.../inplace.vector.capacity/empty.verify.cpp | 30 +
.../inplace.vector.capacity/max_size.pass.cpp | 52 +
.../inplace.vector.capacity/reserve.pass.cpp | 81 ++
.../resize_size.pass.cpp | 49 +
.../resize_size_value.pass.cpp | 73 ++
.../shrink_to_fit.pass.cpp | 41 +
.../inplace.vector.capacity/size.pass.cpp | 82 ++
.../assign_copy.addressof.compile.pass.cpp | 32 +
.../inplace.vector.cons/assign_copy.pass.cpp | 38 +
.../assign_initializer_list.pass.cpp | 77 ++
.../assign_iter_iter.pass.cpp | 119 ++
.../assign_move.addressof.compile.pass.cpp | 33 +
.../inplace.vector.cons/assign_move.pass.cpp | 57 +
.../assign_size_value.pass.cpp | 47 +
.../construct_default.pass.cpp | 73 ++
.../construct_from_range.pass.cpp | 43 +
.../construct_iter_iter.pass.cpp | 177 +++
.../construct_size.pass.cpp | 82 ++
.../construct_size_value.pass.cpp | 60 +
.../copy.move_only.verify.cpp | 27 +
.../inplace.vector.cons/copy.pass.cpp | 51 +
.../inplace.vector.cons/deduct.pass.cpp | 57 +
.../default.recursive.empty.pass.cpp | 26 +
.../default.recursive.fail.cpp | 22 +
.../default_noexcept.pass.cpp | 40 +
.../dtor_noexcept.pass.cpp | 45 +
.../inplace.vector.cons/exceptions.pass.cpp | 166 +++
.../initializer_list.pass.cpp | 51 +
.../move.addressof.compile.pass.cpp | 31 +
.../inplace.vector.cons/move.pass.cpp | 55 +
.../move_assign_noexcept.pass.cpp | 51 +
.../move_noexcept.pass.cpp | 49 +
.../op_equal_initializer_list.pass.cpp | 56 +
.../inplace.vector.data/data.pass.cpp | 91 ++
.../inplace.vector.data/data_const.pass.cpp | 94 ++
.../inplace.vector.erasure/erase.pass.cpp | 95 ++
.../inplace.vector.erasure/erase_if.pass.cpp | 94 ++
...rator_concept_conformance.compile.pass.cpp | 97 ++
.../inplace.vector/iterators.pass.cpp | 198 +++
...range_concept_conformance.compile.pass.cpp | 48 +
.../inplace.vector/reverse_iterators.pass.cpp | 92 ++
.../sequences/inplace.vector/types.pass.cpp | 70 ++
.../vector.modifiers/append_range.pass.cpp | 66 +
.../assert.push_back.invalidation.pass.cpp | 56 +
.../vector.modifiers/assign_range.pass.cpp | 74 ++
.../vector.modifiers/clear.pass.cpp | 54 +
.../destroy_elements.pass.cpp | 156 +++
.../emplace.addressof.compile.pass.cpp | 25 +
.../vector.modifiers/emplace.pass.cpp | 156 +++
.../vector.modifiers/emplace_back.pass.cpp | 175 +++
.../vector.modifiers/emplace_extra.pass.cpp | 88 ++
.../erase_iter.addressof.compile.pass.cpp | 23 +
.../vector.modifiers/erase_iter.pass.cpp | 156 +++
...erase_iter_iter.addressof.compile.pass.cpp | 23 +
.../vector.modifiers/erase_iter_iter.pass.cpp | 174 +++
.../insert_iter_initializer_list.pass.cpp | 110 ++
..._iter_iter_iter.addressof.compile.pass.cpp | 31 +
.../insert_iter_iter_iter.pass.cpp | 182 +++
.../insert_iter_lvalue.pass.cpp | 137 +++
...ert_iter_rvalue.addressof.compile.pass.cpp | 25 +
.../insert_iter_rvalue.pass.cpp | 82 ++
...iter_size_value.addressof.compile.pass.cpp | 24 +
.../insert_iter_size_value.pass.cpp | 117 ++
...sert_iter_value.addressof.compile.pass.cpp | 24 +
.../vector.modifiers/insert_range.pass.cpp | 67 +
.../vector.modifiers/pop_back.pass.cpp | 59 +
.../vector.modifiers/push_back.pass.cpp | 105 ++
.../push_back_exception_safety.pass.cpp | 88 ++
.../push_back_rvalue.pass.cpp | 106 ++
.../resize_not_move_insertable.verify.cpp | 47 +
.../swap.addressof.compile.pass.cpp | 33 +
.../vector.modifiers/swap.pass.cpp | 59 +
.../swap_noexcept.compile.pass.cpp | 87 ++
.../vector.special/swap.pass.cpp | 155 +++
.../inplace_vector.version.compile.pass.cpp | 65 +
.../version.version.compile.pass.cpp | 16 +-
.../test/support/test_container_comparisons.h | 39 +
.../generate_feature_test_macro_components.py | 1 -
libcxx/utils/libcxx/header_information.py | 2 +-
105 files changed, 7533 insertions(+), 23 deletions(-)
create mode 100644 libcxx/include/inplace_vector
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/access.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/compare.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/compare.three_way.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/constant_initialization.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/contiguous.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/empy_type.compile.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/capacity.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/empty.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/empty.verify.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/max_size.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/reserve.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/resize_size.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/resize_size_value.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/shrink_to_fit.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/size.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_copy.addressof.compile.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_copy.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_initializer_list.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_iter_iter.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_move.addressof.compile.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_move.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_size_value.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_default.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_from_range.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_iter_iter.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_size.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_size_value.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/copy.move_only.verify.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/copy.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/deduct.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/default.recursive.empty.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/default.recursive.fail.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/default_noexcept.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/dtor_noexcept.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/exceptions.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/initializer_list.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move.addressof.compile.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move_assign_noexcept.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move_noexcept.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/op_equal_initializer_list.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.data/data.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.data/data_const.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.erasure/erase.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.erasure/erase_if.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/iterator_concept_conformance.compile.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/iterators.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/range_concept_conformance.compile.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/reverse_iterators.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/types.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/append_range.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/assert.push_back.invalidation.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/assign_range.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/clear.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/destroy_elements.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace.addressof.compile.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace_back.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace_extra.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter.addressof.compile.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter_iter.addressof.compile.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter_iter.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_initializer_list.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_iter_iter.addressof.compile.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_iter_iter.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_lvalue.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_rvalue.addressof.compile.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_rvalue.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_size_value.addressof.compile.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_size_value.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_value.addressof.compile.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_range.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/pop_back.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/push_back.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/push_back_exception_safety.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/push_back_rvalue.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/resize_not_move_insertable.verify.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/swap.addressof.compile.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/swap.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/swap_noexcept.compile.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.special/swap.pass.cpp
create mode 100644 libcxx/test/std/language.support/support.limits/support.limits.general/inplace_vector.version.compile.pass.cpp
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index c909a4300db1a6..9f7427e0835502 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -442,7 +442,7 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_hazard_pointer`` *unimplemented*
---------------------------------------------------------- -----------------
- ``__cpp_lib_inplace_vector`` *unimplemented*
+ ``__cpp_lib_inplace_vector`` ``202406L``
---------------------------------------------------------- -----------------
``__cpp_lib_is_virtual_base_of`` ``202406L``
---------------------------------------------------------- -----------------
diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index 8864b1ebe28891..2d0c67d4967b17 100644
--- a/libcxx/docs/Status/Cxx2cPapers.csv
+++ b/libcxx/docs/Status/Cxx2cPapers.csv
@@ -69,7 +69,7 @@
"`P3168R2 <https://wg21.link/P3168R2>`__","Give ``std::optional`` Range Support","2024-06 (St. Louis)","","",""
"`P3217R0 <https://wg21.link/P3217R0>`__","Adjoints to 'Enabling list-initialization for algorithms': find_last","2024-06 (St. Louis)","","",""
"`P2985R0 <https://wg21.link/P2985R0>`__","A type trait for detecting virtual base classes","2024-06 (St. Louis)","|Complete|","20.0",""
-"`P0843R14 <https://wg21.link/P0843R14>`__","``inplace_vector``","2024-06 (St. Louis)","","",""
+"`P0843R14 <https://wg21.link/P0843R14>`__","``inplace_vector``","2024-06 (St. Louis)","|Complete|","20.0",""
"`P3235R3 <https://wg21.link/P3235R3>`__","``std::print`` more types faster with less memory","2024-06 (St. Louis)","","",""
"`P2968R2 <https://wg21.link/P2968R2>`__","Make ``std::ignore`` a first-class object","2024-06 (St. Louis)","|Complete|","19.0",""
"`P2075R6 <https://wg21.link/P2075R6>`__","Philox as an extension of the C++ RNG engines","2024-06 (St. Louis)","","",""
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 8c61009167ddce..4c4e19cf420dbe 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -955,6 +955,7 @@ set(files
functional
future
initializer_list
+ inplace_vector
inttypes.h
iomanip
ios
diff --git a/libcxx/include/__configuration/abi.h b/libcxx/include/__configuration/abi.h
index 707e10b5ceb53f..c66a2385e95394 100644
--- a/libcxx/include/__configuration/abi.h
+++ b/libcxx/include/__configuration/abi.h
@@ -160,7 +160,8 @@
//
// Supported containers:
// - `span`;
-// - `string_view`.
+// - `string_view`;
+// - `inplace_vector`.
// #define _LIBCPP_ABI_BOUNDED_ITERATORS
// Changes the iterator type of `basic_string` to a bounded iterator that keeps track of whether it's within the bounds
diff --git a/libcxx/include/__iterator/wrap_iter.h b/libcxx/include/__iterator/wrap_iter.h
index 549d8ff2dbd7db..318616b32b2633 100644
--- a/libcxx/include/__iterator/wrap_iter.h
+++ b/libcxx/include/__iterator/wrap_iter.h
@@ -108,6 +108,10 @@ class __wrap_iter {
friend class _LIBCPP_TEMPLATE_VIS span;
template <class _Tp, size_t _Size>
friend struct array;
+#if _LIBCPP_STD_VER >= 26
+ template <class _Tp, size_t _Capacity>
+ friend class inplace_vector;
+#endif
};
template <class _Iter1>
diff --git a/libcxx/include/__std_clang_module b/libcxx/include/__std_clang_module
index a21ed26addfe8e..06b0912c4bef12 100644
--- a/libcxx/include/__std_clang_module
+++ b/libcxx/include/__std_clang_module
@@ -97,6 +97,7 @@
#include <functional>
#include <future>
#include <initializer_list>
+#include <inplace_vector>
#include <inttypes.h>
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
# include <iomanip>
diff --git a/libcxx/include/inplace_vector b/libcxx/include/inplace_vector
new file mode 100644
index 00000000000000..22409523f02a21
--- /dev/null
+++ b/libcxx/include/inplace_vector
@@ -0,0 +1,1091 @@
+// -*- 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
+
+// mostly freestanding
+#include <compare> // see [compare.syn]
+#include <initializer_list> // see [initializer.list.syn]
+
+namespace std {
+ // [inplace.vector], class template inplace_vector
+ template<class T, size_t N>
+ class inplace_vector { // partially freestanding
+ 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] size/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 pointer try_emplace_back(Args&&... args);
+ constexpr pointer try_push_back(const T& x);
+ constexpr pointer try_push_back(T&& x);
+ template<container-compatible-range<T> R>
+ constexpr ranges::borrowed_iterator_t<R> try_append_range(R&& rg);
+
+ 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;
+
+ constexpr friend bool operator==(const inplace_vector& x,
+ const inplace_vector& y);
+ constexpr friend synth-three-way-result<T>
+ operator<=>(const inplace_vector& x, const inplace_vector& y);
+ constexpr friend 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); }
+ };
+
+ // [inplace.vector.erasure], erasure
+ template<class T, size_t N, class U = T>
+ constexpr typename inplace_vector<T, N>::size_type
+ erase(inplace_vector<T, N>& c, const U& value);
+ template<class T, size_t N, class Predicate>
+ constexpr typename inplace_vector<T, N>::size_type
+ erase_if(inplace_vector<T, N>& c, Predicate pred);
+} // namespace std
+*/
+
+#include <__algorithm/copy.h>
+#include <__algorithm/equal.h>
+#include <__algorithm/lexicographical_compare_three_way.h>
+#include <__algorithm/min.h>
+#include <__algorithm/move.h>
+#include <__algorithm/move_backward.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 <__config>
+#include <__cstddef/size_t.h>
+#include <__iterator/distance.h>
+#include <__iterator/iterator_traits.h>
+#include <__iterator/move_iterator.h>
+#include <__iterator/reverse_iterator.h>
+#include <__iterator/size.h>
+#include <__iterator/wrap_iter.h>
+#include <__memory/addressof.h>
+#include <__memory/construct_at.h>
+#include <__memory/pointer_traits.h>
+#include <__memory/voidify.h>
+#include <__ranges/access.h>
+#include <__ranges/concepts.h>
+#include <__ranges/container_compatible_range.h>
+#include <__ranges/dangling.h>
+#include <__ranges/from_range.h>
+#include <__type_traits/conditional.h>
+#include <__type_traits/is_nothrow_assignable.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_destructible.h>
+#include <__type_traits/is_trivially_relocatable.h>
+#include <__utility/cmp.h>
+#include <__utility/forward.h>
+#include <__utility/unreachable.h>
+#include <new>
+#include <stdexcept>
+
+// standard-mandated includes
+
+// [inplace.vector.syn]
+#include <compare>
+#include <initializer_list>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 26
+
+template <class _Tp, size_t _Capacity>
+class _LIBCPP_TEMPLATE_VIS inplace_vector;
+
+template <size_t _MaximumPadding, size_t _Capacity>
+_LIBCPP_HIDE_FROM_ABI auto __inplace_vector_size_type() {
+ if constexpr (_MaximumPadding >= sizeof(size_t)) {
+ // Unconditionally use size_t in this case. Using a smaller size
+ // will not change the size of the inplace_vector because it will
+ // only introduce more padding bits
+ return static_cast<size_t>(0);
+ } else if constexpr (_Capacity <= static_cast<unsigned char>(-1) && (sizeof(unsigned char) < sizeof(size_t))) {
+ return static_cast<unsigned char>(0);
+ } else if constexpr (_Capacity <= static_cast<unsigned short>(-1) && (sizeof(unsigned short) < sizeof(size_t))) {
+ return static_cast<unsigned short>(0);
+ } else if constexpr (_Capacity <= static_cast<unsigned int>(-1) && (sizeof(unsigned int) < sizeof(size_t))) {
+ return static_cast<unsigned int>(0);
+ } else if constexpr (_Capacity <= static_cast<unsigned long>(-1) && (sizeof(unsigned long) < sizeof(size_t))) {
+ return static_cast<unsigned long>(0);
+ } else {
+ return static_cast<size_t>(0);
+ }
+}
+
+[[__noreturn__]] _LIBCPP_HIDE_FROM_ABI inline void __inplace_vector_throw_out_of_range() {
+ __throw_out_of_range("inplace_vector");
+ unreachable();
+}
+
+template <class _Tp, size_t _Capacity>
+class _LIBCPP_TEMPLATE_VIS __inplace_vector_array {
+ friend inplace_vector<_Tp, _Capacity>;
+ using __small_size_type = decltype(__inplace_vector_size_type<alignof(_Tp), _Capacity>());
+
+ union {
+ _Tp __elems_[_Capacity];
+ };
+ __small_size_type __sz_;
+
+ // When __constexpr is true, do not actually destroy any elements
+ // so that this can be used as a constexpr variable (otherwise it
+ // would be rejected for being uninitialized)
+ static constexpr bool __constexpr = is_trivially_default_constructible_v<_Tp> && is_trivially_destructible_v<_Tp>;
+ static constexpr bool __trivial_copy_construct = is_trivially_copy_constructible_v<_Tp>;
+ static constexpr bool __trivial_move_construct = is_trivially_move_constructible_v<_Tp>;
+ static constexpr bool __trivial_copy_assign =
+ is_trivially_destructible_v<_Tp> && is_trivially_copy_constructible_v<_Tp> && is_trivially_copy_assignable_v<_Tp>;
+ static constexpr bool __trivial_move_assign =
+ is_trivially_destructible_v<_Tp> && is_trivially_move_constructible_v<_Tp> && is_trivially_move_assignable_v<_Tp>;
+
+ constexpr _LIBCPP_HIDE_FROM_ABI __inplace_vector_array() noexcept : __sz_(0) {
+ if consteval {
+ extern _LIBCPP_HIDE_FROM_ABI void
+ __this_inplace_vector_cannot_be_used_in_a_constant_expression_because_the_type_is_not_trivial();
+ __this_inplace_vector_cannot_be_used_in_a_constant_expression_because_the_type_is_not_trivial();
+ }
+
+ // Start the lifetime of the array without starting the lifetime
+ // of any of its elements
+ // TODO: When start_lifetime_as is implemented on all compilers, remove
+ // this conditional
+# ifdef __cpp_lib_start_lifetime_as
+ std::start_lifetime_as<_Tp[_Capacity]>(__elems_);
+# else
+ ::new (std::__voidify(__elems_)) unsigned char[sizeof(_Tp[_Capacity])];
+# endif
+ }
+ constexpr _LIBCPP_HIDE_FROM_ABI __inplace_vector_array() noexcept
+ requires(__constexpr)
+ : __elems_(), __sz_(0) {
+ if !consteval {
+ std::destroy(__elems_, __elems_ + _Capacity);
+ }
+ }
+ constexpr _LIBCPP_HIDE_FROM_ABI __inplace_vector_array(const __inplace_vector_array&) noexcept
+ /* strengthened */
+ requires(__trivial_copy_construct)
+ = default;
+ constexpr _LIBCPP_HIDE_FROM_ABI __inplace_vector_array(__inplace_vector_array&&) noexcept
+ /* strengthened */
+ requires(__trivial_move_construct)
+ = default;
+
+ constexpr _LIBCPP_HIDE_FROM_ABI ~__inplace_vector_array() {
+ __small_size_type __size = __sz_;
+ __sz_ = 0;
+ std::destroy(__elems_, __elems_ + __size);
+ }
+ constexpr _LIBCPP_HIDE_FROM_ABI ~__inplace_vector_array()
+ requires(is_trivially_destructible_v<_Tp>)
+ = default;
+
+ constexpr _LIBCPP_HIDE_FROM_ABI __inplace_vector_array& operator=(const __inplace_vector_array&) noexcept
+ requires(__trivial_copy_assign)
+ = default;
+ constexpr _LIBCPP_HIDE_FROM_ABI __inplace_vector_array& operator=(__inplace_vector_array&&) noexcept
+ requires(__trivial_move_assign)
+ = default;
+
+ using __trivially_relocatable =
+ __conditional_t<__libcpp_is_trivially_relocatable<_Tp>::value, inplace_vector<_Tp, _Capacity>, void>;
+};
+
+template <class _Tp>
+class _LIBCPP_TEMPLATE_VIS __inplace_vector_array<_Tp, 0> {
+private:
+ friend inplace_vector<_Tp, 0>;
+ using __small_size_type = size_t;
+
+ static constexpr bool __constexpr = true;
+ static constexpr bool __trivial_copy_construct = true;
+ static constexpr bool __trivial_move_construct = true;
+ static constexpr bool __trivial_copy_assign = true;
+ static constexpr bool __trivial_move_assign = true;
+
+ static_assert((static_cast<_Tp (*)[1]>(nullptr) == nullptr), "inplace_vector<T, 0> must still have a valid T");
+ static constexpr _Tp* __elems_ = nullptr;
+ static constexpr __small_size_type __sz_ = 0;
+
+ constexpr _LIBCPP_HIDE_FROM_ABI __inplace_vector_array() noexcept = default;
+ constexpr _LIBCPP_HIDE_FROM_ABI __inplace_vector_array(const __inplace_vector_array&) noexcept /* strengthened */ =
+ default;
+ constexpr _LIBCPP_HIDE_FROM_ABI __inplace_vector_array(__inplace_vector_array&&) noexcept = default;
+ constexpr _LIBCPP_HIDE_FROM_ABI ~__inplace_vector_array() = default;
+
+ constexpr _LIBCPP_HIDE_FROM_ABI __inplace_vector_array& operator=(const __inplace_vector_array&) noexcept = default;
+ constexpr _LIBCPP_HIDE_FROM_ABI __inplace_vector_array& operator=(__inplace_vector_array&&) noexcept = default;
+
+ using __trivially_relocatable = inplace_vector<_Tp, 0>;
+};
+
+template <class _Tp, size_t _Capacity>
+class _LIBCPP_TEMPLATE_VIS inplace_vector : private __inplace_vector_array<_Tp, _Capacity> {
+ using __base = __inplace_vector_array<_Tp, _Capacity>;
+ using __base::__elems_, __base::__sz_;
+ using __small_size_type = __base::__small_size_type;
+
+ static constexpr _LIBCPP_HIDE_FROM_ABI bool __do_destroy() noexcept {
+ if consteval {
+ // Do not destroy elements of the array in a constant expression
+ return !__base::__constexpr;
+ }
+ return true;
+ }
+
+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;
+# ifdef _LIBCPP_ABI_BOUNDED_ITERATORS
+ using iterator = __bounded_iter<__wrap_iter<pointer>>;
+ using const_iterator = __bounded_iter<__wrap_iter<const_pointer>>;
+# else
+ using iterator = __wrap_iter<pointer>;
+ using const_iterator = __wrap_iter<const_pointer>;
+# endif
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+ using __trivially_relocatable = __base::__trivially_relocatable;
+
+ // [inplace.vector.cons], construct/copy/destroy
+ constexpr _LIBCPP_HIDE_FROM_ABI inplace_vector() noexcept = default;
+ constexpr _LIBCPP_HIDE_FROM_ABI explicit inplace_vector(size_type __n) : inplace_vector() {
+ if (__n > capacity())
+ __throw_bad_alloc();
+ // TODO: investigate optimization for trivially constructible _Tp that,
+ // for small _Capacity, unconditionally value_construct all the elements to turn
+ // "memset(data(), 0, sizeof(_Tp) * __n)" into
+ // "memset(data(), 0, sizeof(_Tp[_Capacity]))" which might optimize better
+ for (size_type __i = 0; __i < __n; ++__i) {
+ unchecked_emplace_back();
+ _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__i + 1zu == __sz_, "inplace_vector modified before its lifetime began");
+ }
+ }
+ constexpr _LIBCPP_HIDE_FROM_ABI inplace_vector(size_type __n, const _Tp& __value) : inplace_vector() {
+ if (__n > capacity())
+ __throw_bad_alloc();
+ for (size_type __i = 0; __i < __n; ++__i) {
+ unchecked_emplace_back(__value);
+ _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__i + 1zu == __sz_, "inplace_vector modified before its lifetime began");
+ }
+ }
+
+ // NOTE: [sequence.reqmts]p(67.1) does not apply to this constructor but apply
+ // it anyways so the (size_type, const T&) constructor can never be ambiguous
+ template <class _InputIterator>
+ requires(__has_input_iterator_category<_InputIterator>::value)
+ constexpr _LIBCPP_HIDE_FROM_ABI inplace_vector(_InputIterator __first, _InputIterator __last) : inplace_vector() {
+ if constexpr (__has_forward_iterator_category<_InputIterator>::value) {
+ __append_with_size(__first, __last, std::distance(__first, __last));
+ return;
+ }
+ __append_with_sentinel(__first, __last);
+ }
+ template <_ContainerCompatibleRange<_Tp> _Range>
+ constexpr _LIBCPP_HIDE_FROM_ABI inplace_vector(from_range_t, _Range&& __rg) : inplace_vector() {
+ append_range<true>(__rg);
+ }
+ constexpr _LIBCPP_HIDE_FROM_ABI
+ inplace_vector(const inplace_vector& __other) noexcept(is_nothrow_copy_constructible_v<_Tp>) /* strengthened */
+ : inplace_vector() {
+ _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(this != std::addressof(__other), "inplace_vector self-assign");
+ __small_size_type __expected_size = __other.__sz_;
+ for (__small_size_type __i = 0; __i < __expected_size; ++__i) {
+ unchecked_push_back(__other.data()[__i]);
+ _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__i + 1zu == __sz_, "inplace_vector modified before it's lifetime began");
+ _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
+ __other.__sz_ == __expected_size, "inplace_vector modified while it's being copied from");
+ }
+ }
+ constexpr _LIBCPP_HIDE_FROM_ABI inplace_vector(const inplace_vector&) noexcept
+ /* strengthened */
+ requires(__base::__trivial_copy_construct)
+ = default;
+ constexpr _LIBCPP_HIDE_FROM_ABI
+ inplace_vector(inplace_vector&& __other) noexcept(is_nothrow_move_constructible_v<_Tp>) /* strengthened */
+ : inplace_vector() {
+ _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(this != std::addressof(__other), "inplace_vector self-assign");
+ __small_size_type __expected_size = __other.__sz_;
+ for (__small_size_type __i = 0; __i < __expected_size; ++__i) {
+ unchecked_push_back(std::move(__other.data()[__i]));
+ _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__i + 1zu == __sz_, "inplace_vector modified before it's lifetime began");
+ _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
+ __other.__sz_ == __expected_size, "inplace_vector modified while it's being copied from");
+ }
+ }
+ constexpr _LIBCPP_HIDE_FROM_ABI inplace_vector(inplace_vector&&) noexcept
+ /* strengthened */
+ requires(__base::__trivial_move_construct)
+ = default;
+ constexpr _LIBCPP_HIDE_FROM_ABI inplace_vector(initializer_list<_Tp> __il)
+ : inplace_vector(__il.begin(), __il.end()) {}
+
+ constexpr _LIBCPP_HIDE_FROM_ABI inplace_vector& operator=(const inplace_vector& __other) noexcept(
+ is_nothrow_copy_assignable_v<_Tp> && is_nothrow_copy_constructible_v<_Tp>) /* strengthened */ {
+ static_assert(_Capacity != 0, "Should have picked the trivial operator");
+ if (this != std::addressof(__other)) [[likely]] {
+ __small_size_type __assign = std::min(size(), __other.size());
+ std::copy(__other.data(), __other.data() + __assign, data());
+ if (__other.size() > size()) {
+ __append_with_size(__other.data() + __assign, __other.data() + __other.size(), __other.size() - __assign);
+ } else {
+ __resize_down(__other.size());
+ }
+ }
+ return *this;
+ }
+ constexpr _LIBCPP_HIDE_FROM_ABI inplace_vector& operator=(const inplace_vector&) noexcept
+ /* strengthened */
+ requires(__base::__trivial_copy_assign)
+ = default;
+ constexpr _LIBCPP_HIDE_FROM_ABI inplace_vector& operator=(inplace_vector&& __other) noexcept(
+ is_nothrow_move_assignable_v<_Tp> && is_nothrow_move_constructible_v<_Tp>) {
+ static_assert(_Capacity != 0, "Should have picked the trivial operator");
+ if (this != std::addressof(__other)) [[likely]] {
+ __small_size_type __assign = std::min(size(), __other.size());
+ std::move(__other.data(), __other.data() + __assign, data());
+ if (__other.size() > size()) {
+ __append_with_size(std::make_move_iterator(__other.data() + __assign),
+ std::make_move_iterator(__other.data() + __other.size()),
+ __other.size() - __assign);
+ } else {
+ __resize_down(__other.size());
+ }
+ }
+ return *this;
+ }
+ constexpr _LIBCPP_HIDE_FROM_ABI inplace_vector& operator=(inplace_vector&&) noexcept
+ /* strengthened */
+ requires(__base::__trivial_move_assign)
+ = default;
+
+ constexpr _LIBCPP_HIDE_FROM_ABI ~inplace_vector() = default;
+
+private:
+ constexpr _LIBCPP_HIDE_FROM_ABI iterator __make_iter(pointer __p) const noexcept {
+# ifdef _LIBCPP_ABI_BOUNDED_ITERATORS
+ return std::__make_bounded_iter(__p, __wrap_iter<pointer>(__elems_ + 0), __wrap_iter<pointer>(__elems_ + __sz_));
+# else
+ return iterator(__p);
+# endif
+ }
+
+ constexpr _LIBCPP_HIDE_FROM_ABI const_iterator __make_iter(const_pointer __p) const noexcept {
+ return __make_iter(const_cast<pointer>(__p));
+ }
+
+ template <class _First, class _Sent>
+ constexpr _LIBCPP_HIDE_FROM_ABI void __assign_with_size(_First&& __first, _Sent&& __sent, size_t __n) {
+ if (__n > capacity()) [[unlikely]]
+ __throw_bad_alloc();
+ if constexpr (is_trivially_copyable_v<_Tp>) {
+ clear();
+ __append_with_size(std::forward<_First>(__first), std::forward<_Sent>(__sent), __n);
+ return;
+ }
+ const size_t __initial_size = size();
+ const size_t __assigned_elems = std::min(__initial_size, __n);
+ const size_t __remaining = __n - __assigned_elems;
+ for (size_t __i = 0; __i < __assigned_elems; ++__i) {
+ data()[__i] = *__first;
+ _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__first != __sent, "Iterators modified during assignment or size was wrong");
+ _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
+ size() == __initial_size, "Iterator or assignment modified container size during assign");
+ ++__first;
+ }
+ __append_with_size(std::forward<_First>(__first), std::forward<_Sent>(__sent), __remaining);
+ }
+
+ template <class _First, class _Sent>
+ constexpr _LIBCPP_HIDE_FROM_ABI void __assign_with_sentinel(_First&& __first, _Sent&& __sent) {
+ if constexpr (is_trivially_destructible_v<_Tp>) {
+ clear();
+ __append_with_sentinel(std::forward<_First>(__first), std::forward<_Sent>(__sent));
+ return;
+ }
+ size_t __existing = __sz_;
+ for (size_t __i = 0; __i < __existing; ++__i) {
+ if (__first == __sent)
+ return;
+ data()[__i] = *__first;
+ _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__first != __sent, "Iterators modified during assignment");
+ _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
+ __existing + __i == __sz_, "Iterator or assignment modified container size during assign");
+ ++__first;
+ }
+ __append_with_sentinel(std::forward<_First>(__first), std::forward<_Sent>(__sent));
+ }
+
+public:
+ template <class _InputIterator>
+ requires(__has_input_iterator_category<_InputIterator>::value)
+ constexpr _LIBCPP_HIDE_FROM_ABI void assign(_InputIterator __first, _InputIterator __last) {
+ if constexpr (__has_forward_iterator_category<_InputIterator>::value) {
+ __assign_with_size(__first, __last, std::distance(__first, __last));
+ return;
+ }
+ __assign_with_sentinel(__first, __last);
+ }
+ template <_ContainerCompatibleRange<_Tp> _Range>
+ constexpr _LIBCPP_HIDE_FROM_ABI void assign_range(_Range&& __rg) {
+ if constexpr (ranges::sized_range<_Range&>) {
+ return __assign_with_size(ranges::begin(__rg), ranges::end(__rg), ranges::size(__rg));
+ } else if constexpr (ranges::forward_range<_Range&>) {
+ decltype(auto) __first(ranges::begin(__rg));
+ decltype(auto) __last(ranges::end(__rg));
+ return __assign_with_size(__first, __last, ranges::distance(__first, __last));
+ }
+ return __assign_with_sentinel(ranges::begin(__rg), ranges::end(__rg));
+ }
+ constexpr _LIBCPP_HIDE_FROM_ABI void assign(size_type __n, const _Tp& __u) {
+ if (__n > capacity()) [[unlikely]]
+ __throw_bad_alloc();
+ if constexpr (is_trivially_copyable_v<_Tp>) {
+ clear();
+ } else {
+ const size_t __initial_size = size();
+ const size_t __assigned_elems = std::min(__initial_size, __n);
+ for (size_t __i = 0; __i < __assigned_elems; ++__i) {
+ data()[__i] = __u;
+ _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
+ __sz_ == __initial_size, "inplace_vector element assignment modified container size during assign");
+ }
+ }
+ resize(__n, __u);
+ }
+ constexpr _LIBCPP_HIDE_FROM_ABI void assign(initializer_list<_Tp> __il) { assign(__il.begin(), __il.end()); }
+
+ // iterators
+ constexpr _LIBCPP_HIDE_FROM_ABI iterator begin() noexcept { return __make_iter(data()); }
+ constexpr _LIBCPP_HIDE_FROM_ABI const_iterator begin() const noexcept { return __make_iter(data()); }
+ constexpr _LIBCPP_HIDE_FROM_ABI iterator end() noexcept { return __make_iter(data() + size()); }
+ constexpr _LIBCPP_HIDE_FROM_ABI const_iterator end() const noexcept { return __make_iter(data() + size()); }
+ constexpr _LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
+ constexpr _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rbegin() const noexcept {
+ return const_reverse_iterator(end());
+ }
+ constexpr _LIBCPP_HIDE_FROM_ABI reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
+ constexpr _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend() const noexcept {
+ return const_reverse_iterator(begin());
+ }
+
+ constexpr _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const noexcept { return begin(); }
+ constexpr _LIBCPP_HIDE_FROM_ABI const_iterator cend() const noexcept { return end(); }
+ constexpr _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crbegin() const noexcept { return rbegin(); }
+ constexpr _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const noexcept { return rend(); }
+
+ // [inplace.vector.capacity] size/capacity
+ [[nodiscard]] constexpr _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept { return __sz_ == 0; }
+ [[nodiscard]] constexpr _LIBCPP_HIDE_FROM_ABI size_type size() const noexcept {
+ _LIBCPP_ASSERT_UNCATEGORIZED(__sz_ <= capacity(), "inplace_vector has impossible size");
+ // Let the optimizer know about this inequality
+ if (__sz_ > capacity())
+ unreachable();
+ return __sz_;
+ }
+ [[nodiscard]] static _LIBCPP_HIDE_FROM_ABI constexpr size_type max_size() noexcept { return _Capacity; }
+ [[nodiscard]] static _LIBCPP_HIDE_FROM_ABI constexpr size_type capacity() noexcept { return _Capacity; }
+
+private:
+ constexpr _LIBCPP_HIDE_FROM_ABI void __resize_down(__small_size_type __n) noexcept {
+ _LIBCPP_ASSERT_INTERNAL(__n <= size(), "Trying to __resize_down to a greater number of elements");
+ const const_pointer __old_last = __elems_ + __sz_;
+ const const_pointer __new_last = __elems_ + __n;
+ if constexpr (_Capacity) {
+ __sz_ = __n;
+ }
+ if (__do_destroy())
+ std::destroy(__new_last, __old_last);
+ _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__sz_ == __n, "inplace_vector modified during element destruction");
+ }
+
+ template <class... _Arg>
+ constexpr _LIBCPP_HIDE_FROM_ABI void __resize(size_type __n, const _Arg&... __arg) {
+ if (__n > capacity())
+ __throw_bad_alloc();
+
+ if (__n <= __sz_) {
+ __resize_down(__n);
+ return;
+ }
+
+ size_type __remaining = __n - __sz_;
+ for (size_type __i = 0; __i < __remaining; ++__i) {
+ unchecked_emplace_back(__arg...);
+ }
+ }
+
+public:
+ constexpr _LIBCPP_HIDE_FROM_ABI void resize(size_type __sz) { __resize(__sz); }
+ constexpr _LIBCPP_HIDE_FROM_ABI void resize(size_type __sz, const _Tp& __u) { __resize(__sz, __u); }
+
+ static constexpr _LIBCPP_HIDE_FROM_ABI void reserve(size_type __n) {
+ if (__n > capacity())
+ __throw_bad_alloc();
+ }
+ static constexpr _LIBCPP_HIDE_FROM_ABI void shrink_to_fit() noexcept {}
+
+ // ekenebt access
+ constexpr _LIBCPP_HIDE_FROM_ABI reference operator[](size_type __n) noexcept /* strengthened */ {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "inplace_vector[] index out of bounds");
+ return data()[__n];
+ }
+ constexpr _LIBCPP_HIDE_FROM_ABI const_reference operator[](size_type __n) const noexcept /* strengthened */ {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "inplace_vector[] index out of bounds");
+ return data()[__n];
+ }
+ constexpr reference at(size_type __n) {
+ if (__n >= size())
+ __inplace_vector_throw_out_of_range();
+ return data()[__n];
+ }
+ constexpr const_reference at(size_type __n) const {
+ if (__n >= size())
+ __inplace_vector_throw_out_of_range();
+ return data()[__n];
+ }
+ constexpr _LIBCPP_HIDE_FROM_ABI reference front() noexcept /* strengthened */ {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "front() called on an empty inplace_vector");
+ return *data();
+ }
+ constexpr _LIBCPP_HIDE_FROM_ABI const_reference front() const noexcept /* strengthened */ {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "front() called on an empty inplace_vector");
+ return *data();
+ }
+ constexpr _LIBCPP_HIDE_FROM_ABI reference back() noexcept /* strengthened */ {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty inplace_vector");
+ return data()[__sz_ - __small_size_type(1)];
+ }
+ constexpr _LIBCPP_HIDE_FROM_ABI const_reference back() const noexcept /* strengthened */ {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty inplace_vector");
+ return data()[__sz_ - __small_size_type(1)];
+ }
+
+ // [inplace.vector.daa], data access
+ constexpr _LIBCPP_HIDE_FROM_ABI _Tp* data() noexcept { return __elems_; }
+ constexpr _LIBCPP_HIDE_FROM_ABI const _Tp* data() const noexcept { return __elems_; }
+
+private:
+ template <class _It, class _Sent>
+ constexpr _LIBCPP_HIDE_FROM_ABI void
+ __append_with_size(_It&& __first, [[maybe_unused]] _Sent&& __last, size_type __n) {
+ [[maybe_unused]] __small_size_type __expected_size = size();
+ while (__n--) {
+ _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__first != __last, "Iterators modified during assignment or size was wrong");
+
+ unchecked_emplace_back(*__first);
+ ++__first;
+
+ _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
+ __sz_ == ++__expected_size, "Iterator or assignment modified container size during append");
+ }
+ }
+
+ template <bool _ThrowOnMissingCapacity = true, class _It, class _Sent>
+ constexpr _LIBCPP_HIDE_FROM_ABI void __append_with_sentinel(_It&& __it, _Sent&& __last) {
+ const __small_size_type __initial_size = __sz_;
+ [[maybe_unused]] __small_size_type __expected_size = __sz_;
+ pointer __p = __elems_ + __initial_size;
+ while (__p != __elems_ + capacity()) {
+ if (__it == __last)
+ return;
+ unchecked_emplace_back(*__it);
+ ++__expected_size;
+ ++__it;
+ _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
+ __sz_ == __expected_size, "iterator operation modified container size during append");
+ }
+ if constexpr (_ThrowOnMissingCapacity) {
+ if (__it == __last)
+ return;
+
+ // Exception safety: container must remain unchanged
+ __resize_down(__initial_size);
+ __throw_bad_alloc();
+ }
+ }
+
+ template <bool _ThrowOnMissingCapacity, class _Range>
+ constexpr _LIBCPP_HIDE_FROM_ABI __conditional_t<_ThrowOnMissingCapacity, void, ranges::borrowed_iterator_t<_Range>>
+ __append_range(_Range&& __rg) {
+ decltype(auto) __first(ranges::begin(__rg));
+ size_t __remaining = capacity() - size();
+ if (_ThrowOnMissingCapacity || __remaining != 0) {
+ decltype(auto) __sent(ranges::end(__rg));
+ if constexpr (ranges::sized_range<_Range&>) {
+ auto __n = ranges::size(__rg);
+ size_t __copied;
+ if constexpr (_ThrowOnMissingCapacity) {
+ if (std::cmp_greater(__n, __remaining))
+ __throw_bad_alloc();
+ __copied = static_cast<size_t>(__n);
+ } else {
+ if (std::cmp_greater(__n, __remaining))
+ __copied = __remaining;
+ else
+ __copied = static_cast<size_t>(__n);
+ }
+ __append_with_size(__first, __sent, __copied);
+ } else {
+ __append_with_sentinel<_ThrowOnMissingCapacity>(__first, __sent);
+ }
+ }
+ if constexpr (!_ThrowOnMissingCapacity)
+ return __first;
+ }
+
+public:
+ // [inplace.vector.modifiers], modifiers
+ template <class... _Args>
+ constexpr _LIBCPP_HIDE_FROM_ABI reference emplace_back(_Args&&... __args) {
+ if (size() == capacity()) [[unlikely]]
+ __throw_bad_alloc();
+ return unchecked_emplace_back(std::forward<_Args>(__args)...);
+ }
+ constexpr _LIBCPP_HIDE_FROM_ABI reference push_back(const _Tp& __x) { return emplace_back(__x); }
+ constexpr _LIBCPP_HIDE_FROM_ABI reference push_back(_Tp&& __x) { return emplace_back(std::move(__x)); }
+ template <_ContainerCompatibleRange<_Tp> _Range>
+ constexpr _LIBCPP_HIDE_FROM_ABI void append_range(_Range&& __rg) {
+ __append_range<true>(std::forward<_Range>(__rg));
+ }
+
+ constexpr _LIBCPP_HIDE_FROM_ABI void pop_back() noexcept /* strengthened */ {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "pop_back() called on an empty inplace_vector");
+ if constexpr (_Capacity) {
+ [[maybe_unused]] __small_size_type __expected_size = --__sz_;
+ if (__do_destroy())
+ std::destroy_at(__elems_ + __sz_ - 1);
+ _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
+ __sz_ == __expected_size, "inplace_vector modified during element destruction");
+ } else {
+ unreachable();
+ }
+ }
+
+ template <class... _Args>
+ constexpr _LIBCPP_HIDE_FROM_ABI pointer
+ try_emplace_back(_Args&&... __args) noexcept(is_nothrow_constructible_v<_Tp, _Args...> // strengthened
+ ) {
+ if (size() == capacity())
+ return nullptr;
+ return std::addressof(unchecked_emplace_back(std::forward<_Args>(__args)...));
+ }
+ constexpr _LIBCPP_HIDE_FROM_ABI pointer
+ try_push_back(const _Tp& __x) noexcept(is_nothrow_copy_constructible_v<_Tp>) // strengthened
+ {
+ return try_emplace_back(__x);
+ }
+ constexpr _LIBCPP_HIDE_FROM_ABI pointer
+ try_push_back(_Tp&& __x) noexcept(is_nothrow_move_constructible_v<_Tp> // strengthened
+ ) {
+ return try_emplace_back(std::move(__x));
+ }
+ template <_ContainerCompatibleRange<_Tp> _Range>
+ constexpr _LIBCPP_HIDE_FROM_ABI ranges::borrowed_iterator_t<_Range> try_append_range(_Range&& __rg) {
+ return __append_range<false>(std::forward<_Range>(__rg));
+ }
+
+ template <class... _Args>
+ constexpr _LIBCPP_HIDE_FROM_ABI reference
+ unchecked_emplace_back(_Args&&... __args) noexcept(is_nothrow_constructible_v<_Tp, _Args...> // strengthened
+ ) {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+ size() < capacity(), "unchecked_emplace_back() called on an at-capacity inplace_vector");
+ if constexpr (_Capacity == 0) {
+ unreachable();
+ }
+ pointer __new = data() + size();
+ [[maybe_unused]] size_t __old_size = __sz_;
+ std::construct_at(__new, std::forward<_Args>(__args)...);
+ _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__sz_ == __old_size, "inplace_vector modified during element construction");
+ if constexpr (_Capacity) {
+ ++__sz_;
+ }
+ return *__new;
+ }
+ constexpr _LIBCPP_HIDE_FROM_ABI reference
+ unchecked_push_back(const _Tp& __x) noexcept(is_nothrow_copy_constructible_v<_Tp>) /* strengthened */ {
+ return unchecked_emplace_back(__x);
+ }
+ constexpr _LIBCPP_HIDE_FROM_ABI reference
+ unchecked_push_back(_Tp&& __x) noexcept(is_nothrow_move_constructible_v<_Tp>) /* strengthened */ {
+ return unchecked_emplace_back(std::move(__x));
+ }
+
+private:
+ constexpr _LIBCPP_HIDE_FROM_ABI pointer __unwrap_iter(const_iterator __it) noexcept {
+ return const_cast<pointer>(const_cast<const inplace_vector*>(this)->__unwrap_iter(__it));
+ }
+ constexpr _LIBCPP_HIDE_FROM_ABI const_pointer __unwrap_iter(const_iterator __it) const noexcept {
+ const_pointer __p = std::to_address(__it);
+ if constexpr (_Capacity == 0) {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__p == nullptr, "Not an iterator into this inplace_vector<T, 0>");
+ } else {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+ __elems_ <= __p && __p <= __elems_ + capacity(), "Not an iterator into this inplace_vector");
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__p <= __elems_ + __sz_, "This inplace_vector iterator is invalid");
+ }
+ return __p;
+ }
+
+public:
+ template <class... _Args>
+ constexpr _LIBCPP_HIDE_FROM_ABI iterator emplace(const_iterator __position, _Args&&... __args) {
+ const pointer __p = __unwrap_iter(__position);
+ if (size() == capacity())
+ __throw_bad_alloc();
+
+ if (__p == __elems_ + __sz_) {
+ unchecked_emplace_back(std::forward<_Args>(__args)...);
+ } else if (is_nothrow_constructible_v<_Tp, _Args&&...>) {
+ unchecked_push_back(std::move(back()));
+ std::move_backward(__p, __elems_ + __sz_ - 1, __elems_ + __sz_);
+ std::destroy_at(__p);
+ std::construct_at(__p, std::forward<_Args>(__args)...);
+ } else {
+ unchecked_emplace_back(std::forward<_Args>(__args)...);
+ std::rotate(__p, __elems_ + __sz_ - 1, __elems_ + __sz_);
+ }
+ // (Update bounds for bounded iter)
+ return __make_iter(__p);
+ }
+ constexpr _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __position, const _Tp& __x) {
+ return emplace(__position, __x);
+ }
+ constexpr _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __position, _Tp&& __x) {
+ return emplace(__position, std::move(__x));
+ }
+ constexpr _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __position, size_type __n, const _Tp& __x) {
+ const pointer __p = __unwrap_iter(__position);
+ if (__n > capacity() - size())
+ __throw_bad_alloc();
+
+ if (__p == __elems_ + __sz_) {
+ resize(size() + __n, __x);
+ } else {
+ // Move the last __n elements over into newly constructed elements
+ const pointer __old_end = __elems_ + __sz_;
+ for (size_t __i = 0; __i < __n; ++__i) {
+ unchecked_emplace_back(std::move(__elems_[__sz_ - __n]));
+ }
+ // Move over the remaining elements
+ std::move_backward(__p, __old_end - __n, __old_end);
+ // Insert the elements
+ for (size_t __i = 0; __i < __n; ++__i) {
+ __p[__i] = __x;
+ }
+ }
+ return __make_iter(__p);
+ }
+
+private:
+ template <class _Iterator, class _Sentinel, class _Size>
+ constexpr _LIBCPP_HIDE_FROM_ABI iterator
+ __insert_with_size(const_iterator __position, _Iterator&& __it, _Sentinel&& __sent, _Size __m) {
+ const pointer __p = __unwrap_iter(__position);
+ if (std::cmp_greater(__m, capacity() - size()))
+ __throw_bad_alloc();
+ auto __n = static_cast<__small_size_type>(__m);
+
+ // Exception guarantee: Cannot modify the initial elements if copy/move construct/assign of _Tp throws or if
+ // iterator operations throw, so elements must be rotated in if they can throw. Otherwise, optimise by moving
+ // existing elements "out of the way" first then construct in-place to avoid swapping.
+ bool __can_avoid_rotate = is_nothrow_copy_constructible_v<_Tp> && is_nothrow_move_assignable_v<_Tp> &&
+ noexcept(++__it) && noexcept(*__it) && is_nothrow_constructible_v<_Tp, decltype(*__it)>;
+
+ if (__p == __elems_ + __sz_) {
+ __append_with_size(std::forward<_Iterator>(__it), std::forward<_Sentinel>(__sent), __n);
+ } else if (__can_avoid_rotate) {
+ const pointer __old_end = __elems_ + __sz_;
+ for (size_t __i = 0; __i < __n; ++__i) {
+ unchecked_emplace_back(std::move(__elems_[__sz_ - __n]));
+ }
+ std::move_backward(__p, __old_end - __n, __old_end);
+
+ [[maybe_unused]] __small_size_type __expected_size = __sz_;
+ for (size_t __i = 0; __i < __n; ++__i) {
+ std::destroy_at(__p + __i);
+ // This has already been checked to not throw so the container will never contain a destructed element
+ std::construct_at(__p + __i, *__it);
+ ++__it;
+ _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
+ __sz_ == __expected_size, "inplace_vector modified by iterator operation during insert");
+ }
+ } else {
+ __append_with_size(std::forward<_Iterator>(__it), std::forward<_Sentinel>(__sent), __n);
+ std::rotate(__p, __elems_ + __sz_ - __n, __elems_ + __sz_);
+ }
+ return __make_iter(__p);
+ }
+
+ template <class _Iterator, class _Sentinel>
+ constexpr _LIBCPP_HIDE_FROM_ABI iterator
+ __insert_with_sentinel(const_iterator __position, _Iterator&& __it, _Sentinel&& __sent) {
+ const pointer __p = __unwrap_iter(__position);
+
+ if (__p == __elems_ + __sz_) {
+ __append_with_sentinel(std::forward<_Iterator>(__it), std::forward<_Sentinel>(__sent));
+ } else {
+ const pointer __original_end = __elems_ + __sz_;
+ __append_with_sentinel(std::forward<_Iterator>(__it), std::forward<_Sentinel>(__sent));
+ std::rotate(__p, __original_end, __elems_ + __sz_);
+ }
+ return __make_iter(__p);
+ }
+
+public:
+ template <class _InputIterator>
+ requires(__has_input_iterator_category<_InputIterator>::value)
+ constexpr _LIBCPP_HIDE_FROM_ABI iterator
+ insert(const_iterator __position, _InputIterator __first, _InputIterator __last) {
+ if constexpr (__has_forward_iterator_category<_InputIterator>::value) {
+ return __insert_with_size(__position, __first, __last, std::distance(__first, __last));
+ }
+ return __insert_with_sentinel(__position, __first, __last);
+ }
+ template <_ContainerCompatibleRange<_Tp> _Range>
+ constexpr _LIBCPP_HIDE_FROM_ABI iterator insert_range(const_iterator __position, _Range&& __rg) {
+ decltype(auto) __first(ranges::begin(__rg));
+ decltype(auto) __sent(ranges::end(__rg));
+ if constexpr (ranges::sized_range<_Range&>) {
+ return __insert_with_size(__position, __first, __sent, ranges::size(__rg));
+ } else {
+ return __insert_with_sentinel(__position, __first, __sent);
+ }
+ }
+ constexpr _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __position, initializer_list<_Tp> __il) {
+ return insert(__position, __il.begin(), __il.end());
+ }
+
+ constexpr _LIBCPP_HIDE_FROM_ABI void erase(const_iterator __position) noexcept /* strengthened */ {
+ const pointer __p = __unwrap_iter(__position);
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__p != __elems_ + __sz_, "Cannot erase the end iterator");
+ std::move(__p + 1, __elems_ + __sz_, __p);
+ pop_back();
+ }
+ constexpr _LIBCPP_HIDE_FROM_ABI void erase(const_iterator __first, const_iterator __last) noexcept
+ /* strengthened */ {
+ const pointer __p = __unwrap_iter(__first);
+ const pointer __q = __unwrap_iter(__last);
+ _LIBCPP_ASSERT_VALID_INPUT_RANGE(__p <= __q, "inplace_vector::erase begin iterator is after end iterator");
+ const __small_size_type __erased = __q - __p;
+ std::move(__q, __elems_ + __sz_, __p);
+ __resize_down(__sz_ - __erased);
+ }
+
+ constexpr _LIBCPP_HIDE_FROM_ABI void swap(inplace_vector& __x) noexcept(
+ _Capacity == 0 || (is_nothrow_swappable_v<_Tp> && is_nothrow_move_constructible_v<_Tp>)) {
+ inplace_vector* __smaller = this;
+ inplace_vector* __bigger = std::addressof(__x);
+ __small_size_type __smaller_size = __smaller->__sz_;
+ __small_size_type __bigger_size = __bigger->__sz_;
+ if (__smaller_size > __bigger_size) {
+ std::swap(__smaller, __bigger);
+ std::swap(__smaller_size, __bigger_size);
+ }
+
+ std::swap_ranges(+__smaller->__elems_, __smaller->__elems_ + __smaller_size, +__bigger->__elems_);
+ _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__smaller->__sz_ == __smaller_size && __bigger->__sz_ == __bigger_size,
+ "inplace_vector modified when swapping elements");
+ for (__small_size_type __i = __smaller_size; __i != __bigger_size; ++__i) {
+ unchecked_push_back(std::move(__bigger->data()[__i++]));
+ _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__smaller->__sz_ == __i && __bigger->__sz_ == __bigger_size,
+ "inplace_vector modified when swapping elements");
+ }
+ __bigger->__resize_down(__smaller_size);
+ }
+
+ constexpr _LIBCPP_HIDE_FROM_ABI void clear() noexcept {
+ if constexpr (_Capacity != 0) {
+ __sz_ = 0;
+ }
+ if (__do_destroy())
+ std::destroy(__elems_, __elems_ + __sz_);
+ _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__sz_ == 0, "inplace_vector modified by element destructor during clear()");
+ }
+
+ friend constexpr _LIBCPP_HIDE_FROM_ABI bool operator==(const inplace_vector& __x, const inplace_vector& __y) {
+ size_t __sz = __x.size();
+ if (__sz != __y.size())
+ return false;
+ return std::equal(__x.data(), __x.data() + __sz, __y.data());
+ }
+ // LWG4122
+ friend constexpr _LIBCPP_HIDE_FROM_ABI auto operator<=>(const inplace_vector& __x, const inplace_vector& __y)
+ requires(requires(const _Tp& __t) { __t < __t; })
+ {
+ return std::lexicographical_compare_three_way(
+ __x.data(), __x.data() + __x.size(), __y.data(), __y.data() + __y.size(), std::__synth_three_way);
+ }
+
+ constexpr friend _LIBCPP_HIDE_FROM_ABI void swap(inplace_vector& __x, inplace_vector& __y) noexcept(
+ _Capacity == 0 || (is_nothrow_swappable_v<_Tp> && is_nothrow_move_constructible_v<_Tp>)) {
+ __x.swap(__y);
+ }
+};
+
+template <class _Tp, size_t _Capacity, class _Up>
+constexpr _LIBCPP_HIDE_FROM_ABI size_t erase(inplace_vector<_Tp, _Capacity>& __c, const _Up& __value) noexcept(
+ is_nothrow_move_assignable_v<_Tp> && noexcept(static_cast<bool>(__value == __value)) // strengthened
+) {
+ auto __it = std::remove(__c.begin(), __c.end(), __value);
+ auto __r = __c.end() - __it;
+ __c.erase(__it, __c.end());
+ return __r;
+}
+
+template <class _Tp, size_t _Capacity, class _Predicate>
+constexpr _LIBCPP_HIDE_FROM_ABI size_t erase_if(inplace_vector<_Tp, _Capacity>& __c, _Predicate __pred) noexcept(
+ is_nothrow_move_assignable_v<_Tp> && noexcept(remove_cvref_t<_Predicate>(__pred)) &&
+ noexcept(static_cast<bool>(!declval<remove_cvref_t<_Predicate>&>()(declval<_Tp&>()))) // strengthened
+) {
+ auto __it = std::remove_if(__c.begin(), __c.end(), __pred);
+ auto __r = __c.end() - __it;
+ __c.erase(__it, __c.end());
+ return __r;
+}
+
+#endif // _LIBCPP_STD_VER >= 26
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP_INPLACE_VECTOR
diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index c1181a3622513f..b5bdc58ab8d606 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -140,6 +140,10 @@ module std_initializer_list [system] {
header "initializer_list"
export *
}
+module std_inplace_vector [system] {
+ header "inplace_vector"
+ export *
+}
module std_iomanip [system] {
header "iomanip"
export *
diff --git a/libcxx/include/version b/libcxx/include/version
index 5d679caac0b3b7..0e3cdd4c9070be 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -535,7 +535,7 @@ __cpp_lib_void_t 201411L <type_traits>
// # define __cpp_lib_function_ref 202306L
// # define __cpp_lib_generate_random 202403L
// # define __cpp_lib_hazard_pointer 202306L
-// # define __cpp_lib_inplace_vector 202406L
+# define __cpp_lib_inplace_vector 202406L
# if __has_builtin(__builtin_is_virtual_base_of)
# define __cpp_lib_is_virtual_base_of 202406L
# endif
diff --git a/libcxx/modules/std.compat.cppm.in b/libcxx/modules/std.compat.cppm.in
index 797b413f68e272..8d5cf5400034c6 100644
--- a/libcxx/modules/std.compat.cppm.in
+++ b/libcxx/modules/std.compat.cppm.in
@@ -65,9 +65,6 @@ module;
# if __has_include(<hazard_pointer>)
# error "please update the header information for <hazard_pointer> in headers_not_available in utils/libcxx/header_information.py"
# endif // __has_include(<hazard_pointer>)
-# if __has_include(<inplace_vector>)
-# error "please update the header information for <inplace_vector> in headers_not_available in utils/libcxx/header_information.py"
-# endif // __has_include(<inplace_vector>)
# if __has_include(<linalg>)
# error "please update the header information for <linalg> in headers_not_available in utils/libcxx/header_information.py"
# endif // __has_include(<linalg>)
diff --git a/libcxx/modules/std.cppm.in b/libcxx/modules/std.cppm.in
index 0575774f6f42fd..8cf8a150e5ea0c 100644
--- a/libcxx/modules/std.cppm.in
+++ b/libcxx/modules/std.cppm.in
@@ -72,6 +72,7 @@ module;
#include <functional>
#include <future>
#include <initializer_list>
+#include <inplace_vector>
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
# include <iomanip>
#endif
@@ -173,9 +174,6 @@ module;
# if __has_include(<hazard_pointer>)
# error "please update the header information for <hazard_pointer> in headers_not_available in utils/libcxx/header_information.py"
# endif // __has_include(<hazard_pointer>)
-# if __has_include(<inplace_vector>)
-# error "please update the header information for <inplace_vector> in headers_not_available in utils/libcxx/header_information.py"
-# endif // __has_include(<inplace_vector>)
# if __has_include(<linalg>)
# error "please update the header information for <linalg> in headers_not_available in utils/libcxx/header_information.py"
# endif // __has_include(<linalg>)
diff --git a/libcxx/test/libcxx/transitive_includes/cxx03.csv b/libcxx/test/libcxx/transitive_includes/cxx03.csv
index 506b5cd02c4495..2d0be2fa661f36 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx03.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx03.csv
@@ -938,6 +938,23 @@ future vector
future version
initializer_list cstddef
initializer_list version
+inplace_vector cctype
+inplace_vector cmath
+inplace_vector compare
+inplace_vector cstddef
+inplace_vector cstdint
+inplace_vector cstdlib
+inplace_vector cwchar
+inplace_vector cwctype
+inplace_vector exception
+inplace_vector initializer_list
+inplace_vector iosfwd
+inplace_vector limits
+inplace_vector new
+inplace_vector stdexcept
+inplace_vector type_traits
+inplace_vector typeinfo
+inplace_vector version
iomanip algorithm
iomanip array
iomanip atomic
diff --git a/libcxx/test/libcxx/transitive_includes/cxx11.csv b/libcxx/test/libcxx/transitive_includes/cxx11.csv
index 506b5cd02c4495..2d0be2fa661f36 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx11.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx11.csv
@@ -938,6 +938,23 @@ future vector
future version
initializer_list cstddef
initializer_list version
+inplace_vector cctype
+inplace_vector cmath
+inplace_vector compare
+inplace_vector cstddef
+inplace_vector cstdint
+inplace_vector cstdlib
+inplace_vector cwchar
+inplace_vector cwctype
+inplace_vector exception
+inplace_vector initializer_list
+inplace_vector iosfwd
+inplace_vector limits
+inplace_vector new
+inplace_vector stdexcept
+inplace_vector type_traits
+inplace_vector typeinfo
+inplace_vector version
iomanip algorithm
iomanip array
iomanip atomic
diff --git a/libcxx/test/libcxx/transitive_includes/cxx14.csv b/libcxx/test/libcxx/transitive_includes/cxx14.csv
index 828e1d62c6ec3e..920048db06d454 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx14.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx14.csv
@@ -961,6 +961,23 @@ future vector
future version
initializer_list cstddef
initializer_list version
+inplace_vector cctype
+inplace_vector cmath
+inplace_vector compare
+inplace_vector cstddef
+inplace_vector cstdint
+inplace_vector cstdlib
+inplace_vector cwchar
+inplace_vector cwctype
+inplace_vector exception
+inplace_vector initializer_list
+inplace_vector iosfwd
+inplace_vector limits
+inplace_vector new
+inplace_vector stdexcept
+inplace_vector type_traits
+inplace_vector typeinfo
+inplace_vector version
iomanip algorithm
iomanip array
iomanip atomic
diff --git a/libcxx/test/libcxx/transitive_includes/cxx17.csv b/libcxx/test/libcxx/transitive_includes/cxx17.csv
index 0bee6e9beb7af1..053326b6526e10 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx17.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx17.csv
@@ -962,6 +962,23 @@ future vector
future version
initializer_list cstddef
initializer_list version
+inplace_vector cctype
+inplace_vector cmath
+inplace_vector compare
+inplace_vector cstddef
+inplace_vector cstdint
+inplace_vector cstdlib
+inplace_vector cwchar
+inplace_vector cwctype
+inplace_vector exception
+inplace_vector initializer_list
+inplace_vector iosfwd
+inplace_vector limits
+inplace_vector new
+inplace_vector stdexcept
+inplace_vector type_traits
+inplace_vector typeinfo
+inplace_vector version
iomanip algorithm
iomanip array
iomanip atomic
diff --git a/libcxx/test/libcxx/transitive_includes/cxx20.csv b/libcxx/test/libcxx/transitive_includes/cxx20.csv
index 026c26f3bd9819..488c56973e2a01 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx20.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx20.csv
@@ -948,6 +948,23 @@ future vector
future version
initializer_list cstddef
initializer_list version
+inplace_vector cctype
+inplace_vector cmath
+inplace_vector compare
+inplace_vector cstddef
+inplace_vector cstdint
+inplace_vector cstdlib
+inplace_vector cwchar
+inplace_vector cwctype
+inplace_vector exception
+inplace_vector initializer_list
+inplace_vector iosfwd
+inplace_vector limits
+inplace_vector new
+inplace_vector stdexcept
+inplace_vector type_traits
+inplace_vector typeinfo
+inplace_vector version
iomanip algorithm
iomanip array
iomanip atomic
diff --git a/libcxx/test/libcxx/transitive_includes/cxx23.csv b/libcxx/test/libcxx/transitive_includes/cxx23.csv
index 861fd2bb9ba98f..012ace6f4804cb 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx23.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx23.csv
@@ -517,6 +517,17 @@ future typeinfo
future version
initializer_list cstddef
initializer_list version
+inplace_vector cctype
+inplace_vector compare
+inplace_vector cstddef
+inplace_vector cstdint
+inplace_vector cwchar
+inplace_vector cwctype
+inplace_vector initializer_list
+inplace_vector limits
+inplace_vector new
+inplace_vector stdexcept
+inplace_vector version
iomanip bitset
iomanip cctype
iomanip cerrno
diff --git a/libcxx/test/libcxx/transitive_includes/cxx26.csv b/libcxx/test/libcxx/transitive_includes/cxx26.csv
index a31139f1ee8565..668a4dbe11c7e6 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx26.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx26.csv
@@ -516,6 +516,17 @@ future typeinfo
future version
initializer_list cstddef
initializer_list version
+inplace_vector cctype
+inplace_vector compare
+inplace_vector cstddef
+inplace_vector cstdint
+inplace_vector cwchar
+inplace_vector cwctype
+inplace_vector initializer_list
+inplace_vector limits
+inplace_vector new
+inplace_vector stdexcept
+inplace_vector version
iomanip bitset
iomanip cctype
iomanip cerrno
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/access.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/access.pass.cpp
new file mode 100644
index 00000000000000..9232715d4676a0
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/access.pass.cpp
@@ -0,0 +1,148 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// reference operator[](size_type __i);
+// const_reference operator[](size_type __i) const;
+//
+// reference at(size_type __i);
+// const_reference at(size_type __i) const;
+//
+// reference front();
+// const_reference front() const;
+//
+// reference back();
+// const_reference back() const;
+// libc++ marks these as 'noexcept' (except 'at')
+
+#include <inplace_vector>
+#include <cassert>
+#include <stdexcept>
+
+#include "test_macros.h"
+#include "MoveOnly.h"
+
+template <class C>
+constexpr C make(int size, int start) {
+ C c;
+ for (int i = 0; i < size; ++i)
+ c.push_back(start + i);
+ return c;
+}
+
+template <class Vector>
+constexpr void test_get_basic(Vector& c, int start_value) {
+ const int n = static_cast<int>(c.size());
+ for (int i = 0; i < n; ++i)
+ assert(c[i] == start_value + i);
+ for (int i = 0; i < n; ++i)
+ assert(c.at(i) == start_value + i);
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ if !consteval {
+ try {
+ TEST_IGNORE_NODISCARD c.at(n);
+ assert(false);
+ } catch (const std::out_of_range&) {
+ } catch (...) {
+ assert(false);
+ }
+ }
+#endif
+
+ assert(c.front() == start_value);
+ assert(c.back() == start_value + n - 1);
+}
+
+template <class Vector, bool IsConstexpr>
+constexpr void test_get() {
+ bool can_run = Vector::capacity() >= 10;
+ if consteval {
+ can_run &= IsConstexpr;
+ }
+ if (can_run) {
+ int start_value = 35;
+ Vector c = make<Vector>(10, start_value);
+ const Vector& cc = c;
+ test_get_basic(c, start_value);
+ test_get_basic(cc, start_value);
+ }
+}
+
+template <class Vector, bool IsConstexpr>
+constexpr void test_set() {
+ const int n = 10;
+ bool can_run = Vector::capacity() >= n;
+ if consteval {
+ can_run &= IsConstexpr;
+ }
+ if (can_run) {
+ int start_value = 35;
+ Vector c = make<Vector>(n, start_value);
+
+ for (int i = 0; i < n; ++i) {
+ assert(c[i] == start_value + i);
+ c[i] = start_value + i + 1;
+ assert(c[i] == start_value + i + 1);
+ }
+ for (int i = 0; i < n; ++i) {
+ assert(c.at(i) == start_value + i + 1);
+ c.at(i) = start_value + i + 2;
+ assert(c.at(i) == start_value + i + 2);
+ }
+
+ assert(c.front() == start_value + 2);
+ c.front() = start_value + 3;
+ assert(c.front() == start_value + 3);
+
+ assert(c.back() == start_value + n + 1);
+ c.back() = start_value + n + 2;
+ assert(c.back() == start_value + n + 2);
+ }
+}
+
+template <class Vector, bool IsConstexpr>
+constexpr void test() {
+ test_get<Vector, IsConstexpr>();
+ test_set<Vector, IsConstexpr>();
+
+ union {
+ int _ = 0;
+ Vector c;
+ };
+ const Vector& cc = c;
+ ASSERT_SAME_TYPE(typename Vector::reference, decltype(c[0]));
+ ASSERT_SAME_TYPE(typename Vector::const_reference, decltype(cc[0]));
+
+ ASSERT_SAME_TYPE(typename Vector::reference, decltype(c.at(0)));
+ ASSERT_SAME_TYPE(typename Vector::const_reference, decltype(cc.at(0)));
+
+ ASSERT_SAME_TYPE(typename Vector::reference, decltype(c.front()));
+ ASSERT_SAME_TYPE(typename Vector::const_reference, decltype(cc.front()));
+
+ ASSERT_SAME_TYPE(typename Vector::reference, decltype(c.back()));
+ ASSERT_SAME_TYPE(typename Vector::const_reference, decltype(cc.back()));
+}
+
+constexpr bool tests() {
+ test<std::inplace_vector<int, 0>, true>();
+ test<std::inplace_vector<int, 10>, true>();
+ test<std::inplace_vector<int, 100>, true>();
+ test<std::inplace_vector<MoveOnly, 0>, true>();
+ test<std::inplace_vector<MoveOnly, 10>, false>();
+ test<std::inplace_vector<MoveOnly, 100>, false>();
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/compare.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/compare.pass.cpp
new file mode 100644
index 00000000000000..446349ab2dfe24
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/compare.pass.cpp
@@ -0,0 +1,131 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <vector>
+
+// friend bool operator==(const inplace_vector& lhs, const inplace_vector& rhs);
+// synthesized operator!=
+// constexpr auto operator<=>(const inplace_vector& x,
+// const inplace_vector& y); // synth-three-way-result
+// synthesized operator<, operator>, operator<=, operator>=
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_comparisons.h"
+
+constexpr bool test() {
+ {
+ const std::inplace_vector<int, 0> c1, c2;
+ assert(testComparisons(c1, c2, true, false));
+ }
+ {
+ const std::inplace_vector<int, 10> c1, c2;
+ assert(testComparisons(c1, c2, true, false));
+ }
+ {
+ const std::inplace_vector<int, 10> c1(1, 1), c2(1, 2);
+ assert(testComparisons(c1, c2, false, true));
+ }
+ {
+ const std::inplace_vector<int, 10> c1, c2(1, 2);
+ assert(testComparisons(c1, c2, false, true));
+ }
+ {
+ const std::inplace_vector<int, 10> c1{1, 2, 1};
+ const std::inplace_vector<int, 10> c2{1, 2, 2};
+ assert(testComparisons(c1, c2, false, true));
+ }
+ {
+ const std::inplace_vector<int, 10> c1{3, 2, 3};
+ const std::inplace_vector<int, 10> c2{3, 1, 3};
+
+ assert(testComparisons(c1, c2, false, false));
+ }
+ {
+ const std::inplace_vector<int, 10> c1{1, 2};
+ const std::inplace_vector<int, 10> c2{1, 2, 0};
+ assert(testComparisons(c1, c2, false, true));
+ }
+ {
+ const std::inplace_vector<int, 10> c1{1, 2, 0};
+ const std::inplace_vector<int, 10> c2{3};
+ assert(testComparisons(c1, c2, false, true));
+ }
+ if !consteval {
+ const std::inplace_vector<LessAndEqComp, 0> c1, c2;
+ assert(testComparisons(c1, c2, true, false));
+ }
+ if !consteval {
+ const std::inplace_vector<LessAndEqComp, 10> c1, c2;
+ assert(testComparisons(c1, c2, true, false));
+ }
+ if !consteval {
+ const std::inplace_vector<LessAndEqComp, 10> c1{LessAndEqComp(1)};
+ const std::inplace_vector<LessAndEqComp, 10> c2{LessAndEqComp(1)};
+ assert(testComparisons(c1, c2, true, false));
+ }
+ if !consteval {
+ const std::inplace_vector<LessAndEqComp, 10> c1{LessAndEqComp(1)};
+ const std::inplace_vector<LessAndEqComp, 10> c2{LessAndEqComp(2)};
+ assert(testComparisons(c1, c2, false, true));
+ }
+ if !consteval {
+ const std::inplace_vector<LessAndEqComp, 10> c1;
+ const std::inplace_vector<LessAndEqComp, 10> c2(1, LessAndEqComp(2));
+ assert(testComparisons(c1, c2, false, true));
+ }
+ if !consteval {
+ const std::inplace_vector<LessAndEqComp, 10> c1{LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(2)};
+ const std::inplace_vector<LessAndEqComp, 10> c2{LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(1)};
+ assert(testComparisons(c1, c2, false, false));
+ }
+ if !consteval {
+ const std::inplace_vector<LessAndEqComp, 10> c1{LessAndEqComp(3), LessAndEqComp(3), LessAndEqComp(3)};
+ const std::inplace_vector<LessAndEqComp, 10> c2{LessAndEqComp(3), LessAndEqComp(2), LessAndEqComp(3)};
+ assert(testComparisons(c1, c2, false, false));
+ }
+ if !consteval {
+ const std::inplace_vector<LessAndEqComp, 10> c1{LessAndEqComp(1), LessAndEqComp(2)};
+ const std::inplace_vector<LessAndEqComp, 10> c2{LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(0)};
+ assert(testComparisons(c1, c2, false, true));
+ }
+ if !consteval {
+ const std::inplace_vector<LessAndEqComp, 10> c1{LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(0)};
+ const std::inplace_vector<LessAndEqComp, 10> c2{LessAndEqComp(3)};
+ assert(testComparisons(c1, c2, false, true));
+ }
+ {
+ using V = std::inplace_vector<int, 0>;
+ assert((V() == V()));
+ assert(!(V() != V()));
+ assert(!(V() < V()));
+ assert((V() <= V()));
+ assert(!(V() > V()));
+ assert((V() >= V()));
+ }
+ {
+ using V = std::inplace_vector<int, 10>;
+ assert((V() == V()));
+ assert(!(V() != V()));
+ assert(!(V() < V()));
+ assert((V() <= V()));
+ assert(!(V() > V()));
+ assert((V() >= V()));
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/compare.three_way.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/compare.three_way.pass.cpp
new file mode 100644
index 00000000000000..ce8555dd653ebb
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/compare.three_way.pass.cpp
@@ -0,0 +1,38 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// class inplace_vector
+
+// constexpr auto operator<=>(const inplace_vector& x,
+// const inplace_vector& y);
+
+// FIXME: check if the auto is valid
+
+#include <cassert>
+#include <inplace_vector>
+
+#include "test_container_comparisons.h"
+
+template <typename T>
+using inplace_vector_size_10 = std::inplace_vector<T, 10>;
+template <typename T>
+using inplace_vector_size_0 = std::inplace_vector<T, 0>;
+
+// TODO: test inplace_vector<T, 0> still has a valid definition
+// TODO: modify so that the checks work in constexpr
+
+int main(int, char**) {
+ assert(test_sequence_container_spaceship<inplace_vector_size_10>());
+ static_assert(test_sequence_container_spaceship<inplace_vector_size_10>());
+ assert(test_sequence_container_spaceship<inplace_vector_size_0>());
+ static_assert(test_sequence_container_spaceship<inplace_vector_size_0>());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/constant_initialization.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/constant_initialization.pass.cpp
new file mode 100644
index 00000000000000..5dc7020fa70d85
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/constant_initialization.pass.cpp
@@ -0,0 +1,75 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+#include <inplace_vector>
+#include <type_traits>
+#include <cassert>
+
+struct NonTrivial {
+ bool constant = std::is_constant_evaluated();
+};
+
+constexpr bool tests() {
+ {
+ using V = std::inplace_vector<int, 0>;
+ if !consteval {
+ constinit static V v1;
+ assert(v1.size() == 0);
+ }
+ constexpr static V v2;
+ static_assert(v2.size() == 0);
+ }
+ {
+ using V = std::inplace_vector<int, 10>;
+ if !consteval {
+ constinit static V v1;
+ assert(v1.size() == 0);
+ }
+ constexpr static V v2;
+ static_assert(v2.size() == 0);
+ }
+ {
+ using V = std::inplace_vector<int, 10>;
+ if !consteval {
+ constinit static V v1{1, 2, 3};
+ assert(v1.size() == 3);
+ assert(v1[0] == 1 && v1[1] == 2 && v1[2] == 3);
+ }
+ constexpr static V v2{1, 2, 3};
+ constexpr static V v3 = [] consteval { return V{1, 2, 3}; }();
+ static_assert(v2.size() == 3);
+ static_assert(v3.size() == 3);
+ static_assert(v2[0] == 1 && v2[1] == 2 && v2[2] == 3);
+ static_assert(v3[0] == 1 && v3[1] == 2 && v3[2] == 3);
+ }
+ {
+ using V = std::inplace_vector<NonTrivial, 0>;
+ if !consteval {
+ constinit static V v1;
+ assert(v1.size() == 0);
+ }
+ constexpr static V v2;
+ static_assert(v2.size() == 0);
+ }
+ if !consteval {
+ using V = std::inplace_vector<NonTrivial, 10>;
+ static V v(3);
+ assert(v.size() == 3);
+ assert(!v[0].constant && !v[1].constant && !v[2].constant);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/contiguous.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/contiguous.pass.cpp
new file mode 100644
index 00000000000000..9695135155dffb
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/contiguous.pass.cpp
@@ -0,0 +1,49 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// An inplace_vector is a contiguous container
+
+#include <inplace_vector>
+#include <memory>
+#include <cassert>
+
+#include "test_macros.h"
+
+template <class C>
+constexpr void test_contiguous(const C& c) {
+ for (std::size_t i = 0; i <= c.size(); ++i) {
+ if (i != c.size()) {
+ assert(*(c.begin() + i) == *(std::addressof(*c.begin()) + i));
+ assert(std::addressof(c.begin()[i]) == std::addressof(c.front()) + i);
+ }
+ assert(std::to_address(c.begin() + i) == std::to_address(c.begin()) + i);
+ }
+}
+
+constexpr bool tests() {
+ {
+ using V = std::inplace_vector<int, 10>;
+ test_contiguous(V());
+ test_contiguous(V(3, 5));
+ }
+ {
+ using V = std::inplace_vector<int, 0>;
+ test_contiguous(V());
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/empy_type.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/empy_type.compile.pass.cpp
new file mode 100644
index 00000000000000..6dd0c6109486d9
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/empy_type.compile.pass.cpp
@@ -0,0 +1,33 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_vector
+
+#include <inplace_vector>
+#include <type_traits>
+
+struct NonTrivial {
+ int i = 0;
+};
+struct VeryNonTrivial {
+ VeryNonTrivial();
+ VeryNonTrivial(const VeryNonTrivial&);
+ VeryNonTrivial& operator=(const VeryNonTrivial&);
+ ~VeryNonTrivial();
+};
+struct MoreNonTrivial : virtual VeryNonTrivial {
+ virtual void f();
+};
+
+static_assert(std::is_empty_v<std::inplace_vector<int, 0>>);
+static_assert(std::is_empty_v<std::inplace_vector<NonTrivial, 0>>);
+static_assert(std::is_empty_v<std::inplace_vector<VeryNonTrivial, 0>>);
+static_assert(std::is_empty_v<std::inplace_vector<MoreNonTrivial, 0>>);
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/capacity.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/capacity.pass.cpp
new file mode 100644
index 00000000000000..5f00dd1faecff7
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/capacity.pass.cpp
@@ -0,0 +1,52 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// static size_type capacity() noexcept;
+
+#include <inplace_vector>
+#include <concepts>
+#include <cassert>
+
+#include "test_macros.h"
+#include "MoveOnly.h"
+
+template <typename T, std::size_t N>
+constexpr void test() {
+ using V = std::inplace_vector<T, N>;
+ V v;
+ std::same_as<std::size_t> decltype(auto) sz = v.capacity();
+ assert(sz == N);
+ static_assert(v.capacity() == N);
+ static_assert(V::capacity() == N);
+ ASSERT_NOEXCEPT(v.capacity());
+ ASSERT_NOEXCEPT(V::capacity());
+}
+
+constexpr bool tests() {
+ test<int, 10>();
+ test<int, 0>();
+ test<MoveOnly, 0>();
+ if !consteval {
+ test<MoveOnly, 10>();
+ }
+ {
+ extern std::inplace_vector<MoveOnly, 10> v;
+ assert(v.capacity() == 10);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/empty.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/empty.pass.cpp
new file mode 100644
index 00000000000000..641519c62c0b9a
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/empty.pass.cpp
@@ -0,0 +1,67 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// class inplace_vector
+
+// bool empty() const noexcept;
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "MoveOnly.h"
+
+constexpr bool tests() {
+ {
+ using V = std::inplace_vector<int, 10>;
+ V v;
+ ASSERT_NOEXCEPT(v.empty());
+ assert(v.empty());
+ v.push_back(1);
+ assert(!v.empty());
+ v.clear();
+ assert(v.empty());
+ }
+ {
+ using V = std::inplace_vector<int, 0>;
+ V v;
+ ASSERT_NOEXCEPT(v.empty());
+ assert(v.empty());
+ // Without language extension, since V is an empty type, there is no way for this to *not* be a constant expression
+ static_assert(v.empty());
+ }
+ {
+ using V = std::inplace_vector<MoveOnly, 0>;
+ V v;
+ ASSERT_NOEXCEPT(v.empty());
+ assert(v.empty());
+ // See above
+ static_assert(v.empty());
+ }
+ if !consteval {
+ using V = std::inplace_vector<MoveOnly, 10>;
+ V v;
+ ASSERT_NOEXCEPT(v.empty());
+ assert(v.empty());
+ v.push_back(V::value_type(1));
+ assert(!v.empty());
+ v.clear();
+ assert(v.empty());
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/empty.verify.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/empty.verify.cpp
new file mode 100644
index 00000000000000..6bbb82b40dd72c
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/empty.verify.cpp
@@ -0,0 +1,30 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// class inplace_vector
+
+// bool empty() const noexcept;
+
+// See also: https://wg21.link/P2422R0
+// In practice, this should be marked [[no_discard]]
+
+#include <inplace_vector>
+
+void f() {
+ {
+ std::inplace_vector<int, 10> c;
+ c.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ }
+ {
+ std::inplace_vector<int, 0> c;
+ c.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ }
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/max_size.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/max_size.pass.cpp
new file mode 100644
index 00000000000000..b71210a22580a7
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/max_size.pass.cpp
@@ -0,0 +1,52 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// static size_type max_size() noexcept;
+
+#include <inplace_vector>
+#include <concepts>
+#include <cassert>
+
+#include "test_macros.h"
+#include "MoveOnly.h"
+
+template <typename T, std::size_t N>
+constexpr void test() {
+ using V = std::inplace_vector<T, N>;
+ V v;
+ std::same_as<std::size_t> decltype(auto) sz = v.max_size();
+ assert(sz == N);
+ static_assert(v.max_size() == N);
+ static_assert(V::max_size() == N);
+ ASSERT_NOEXCEPT(v.max_size());
+ ASSERT_NOEXCEPT(V::max_size());
+}
+
+constexpr bool tests() {
+ test<int, 10>();
+ test<int, 0>();
+ test<MoveOnly, 0>();
+ if !consteval {
+ test<MoveOnly, 10>();
+ }
+ {
+ extern std::inplace_vector<MoveOnly, 10> v;
+ assert(v.max_size() == 10);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/reserve.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/reserve.pass.cpp
new file mode 100644
index 00000000000000..31081d4c6f2f15
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/reserve.pass.cpp
@@ -0,0 +1,81 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// static void reserve(size_type n);
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "MoveOnly.h"
+
+constexpr bool tests() {
+ {
+ using V = std::inplace_vector<int, 10>;
+ V v;
+ for (int i = 0; i <= 10; ++i) {
+ v.reserve(i);
+ }
+ static_assert((v.reserve(0), v.reserve(1), v.reserve(2), v.reserve(8), v.reserve(9), v.reserve(10), true));
+ static_assert((V::reserve(0), V::reserve(1), V::reserve(2), V::reserve(8), V::reserve(9), V::reserve(10), true));
+ if !consteval {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ try {
+ V::reserve(11);
+ assert(false);
+ } catch (const std::bad_alloc&) {
+ } catch (...) {
+ assert(false);
+ }
+ try {
+ V::reserve(-1);
+ assert(false);
+ } catch (const std::bad_alloc&) {
+ } catch (...) {
+ assert(false);
+ }
+#endif
+ }
+ }
+ {
+ using V = std::inplace_vector<int, 0>;
+ V v;
+ v.reserve(0);
+ static_assert((v.reserve(0), true));
+ static_assert((V::reserve(0), true));
+ if !consteval {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ try {
+ V::reserve(1);
+ assert(false);
+ } catch (const std::bad_alloc&) {
+ } catch (...) {
+ assert(false);
+ }
+ try {
+ V::reserve(-1);
+ assert(false);
+ } catch (const std::bad_alloc&) {
+ } catch (...) {
+ assert(false);
+ }
+#endif
+ }
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/resize_size.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/resize_size.pass.cpp
new file mode 100644
index 00000000000000..d67fe2986240de
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/resize_size.pass.cpp
@@ -0,0 +1,49 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// void resize(size_type sz);
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "MoveOnly.h"
+
+constexpr bool tests() {
+ {
+ std::inplace_vector<int, 400> v(100);
+ v.resize(50);
+ assert(v.size() == 50);
+ for (int i : v) {
+ assert(i == 0);
+ }
+ v.resize(200);
+ assert(v.size() == 200);
+ for (int i : v) {
+ assert(i == 0);
+ }
+ }
+ if !consteval {
+ std::inplace_vector<MoveOnly, 400> v(100);
+ v.resize(50);
+ assert(v.size() == 50);
+ v.resize(200);
+ assert(v.size() == 200);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/resize_size_value.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/resize_size_value.pass.cpp
new file mode 100644
index 00000000000000..4cc65dd73ca48a
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/resize_size_value.pass.cpp
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// void resize(size_type sz);
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+
+struct NonTrivial {
+ int i;
+ NonTrivial() : i(0) {}
+ NonTrivial(int i) : i(i) {}
+ NonTrivial(const NonTrivial& other) : i(other.i) {}
+ NonTrivial& operator=(const NonTrivial& other) {
+ i = other.i;
+ return *this;
+ }
+ ~NonTrivial() {}
+ operator int() const { return i; }
+};
+
+constexpr bool tests() {
+ {
+ std::inplace_vector<int, 400> v(100);
+ v.resize(50, 1);
+ assert(v.size() == 50);
+ for (int i : v) {
+ assert(i == 0);
+ }
+ v.resize(200, 1);
+ assert(v.size() == 200);
+ for (int i = 0; i < 50; ++i) {
+ assert(v[i] == 0);
+ }
+ for (int i = 50; i < 200; ++i) {
+ assert(v[i] == 1);
+ }
+ }
+ if !consteval {
+ std::inplace_vector<NonTrivial, 400> v(100);
+ v.resize(50, 1);
+ assert(v.size() == 50);
+ for (int i : v) {
+ assert(i == 0);
+ }
+ v.resize(200, 1);
+ assert(v.size() == 200);
+ for (int i = 0; i < 50; ++i) {
+ assert(v[i] == 0);
+ }
+ for (int i = 50; i < 200; ++i) {
+ assert(v[i] == 1);
+ }
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/shrink_to_fit.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/shrink_to_fit.pass.cpp
new file mode 100644
index 00000000000000..bb1c1b3eb65e34
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/shrink_to_fit.pass.cpp
@@ -0,0 +1,41 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// static void shrink_to_fit() noexcept;
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "MoveOnly.h"
+
+template <typename T, std::size_t N>
+constexpr void test() {
+ using V = std::inplace_vector<T, N>;
+ static_assert((V::shrink_to_fit(), true));
+ ASSERT_NOEXCEPT(V::shrink_to_fit());
+}
+
+constexpr bool tests() {
+ test<int, 10>();
+ test<int, 0>();
+ test<MoveOnly, 10>();
+ test<MoveOnly, 0>();
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/size.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/size.pass.cpp
new file mode 100644
index 00000000000000..30acc72fe69ee4
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/size.pass.cpp
@@ -0,0 +1,82 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// class vector
+
+// size_type size() const noexcept;
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "MoveOnly.h"
+
+constexpr bool tests() {
+ {
+ using V = std::inplace_vector<int, 10>;
+ V v;
+ ASSERT_NOEXCEPT(v.size());
+ assert(v.size() == 0);
+ v.push_back(2);
+ assert(v.size() == 1);
+ v.push_back(1);
+ assert(v.size() == 2);
+ v.push_back(3);
+ assert(v.size() == 3);
+ v.erase(v.begin());
+ assert(v.size() == 2);
+ v.erase(v.begin());
+ assert(v.size() == 1);
+ v.erase(v.begin());
+ assert(v.size() == 0);
+ }
+ if !consteval {
+ using V = std::inplace_vector<MoveOnly, 10>;
+ V v;
+ ASSERT_NOEXCEPT(v.size());
+ assert(v.size() == 0);
+ v.push_back(2);
+ assert(v.size() == 1);
+ v.push_back(1);
+ assert(v.size() == 2);
+ v.push_back(3);
+ assert(v.size() == 3);
+ v.erase(v.begin());
+ assert(v.size() == 2);
+ v.erase(v.begin());
+ assert(v.size() == 1);
+ v.erase(v.begin());
+ assert(v.size() == 0);
+ }
+ {
+ using V = std::inplace_vector<int, 0>;
+ V v;
+ ASSERT_NOEXCEPT(v.size());
+ assert(v.size() == 0);
+ // Without language extension, since V is an empty type, there is no way for this to *not* be a constant expression
+ static_assert(v.size() == 0);
+ }
+ {
+ using V = std::inplace_vector<MoveOnly, 0>;
+ V v;
+ ASSERT_NOEXCEPT(v.size());
+ assert(v.size() == 0);
+ // See above
+ static_assert(v.size() == 0);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_copy.addressof.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_copy.addressof.compile.pass.cpp
new file mode 100644
index 00000000000000..be798ea00d231d
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_copy.addressof.compile.pass.cpp
@@ -0,0 +1,32 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_vector& operator=(const inplace_vector& c);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <inplace_vector>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+ {
+ std::inplace_vector<operator_hijacker, 10> vo;
+ std::inplace_vector<operator_hijacker, 10> v;
+ v = vo;
+ }
+ {
+ std::inplace_vector<operator_hijacker, 0> vo;
+ std::inplace_vector<operator_hijacker, 0> v;
+ v = vo;
+ }
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_copy.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_copy.pass.cpp
new file mode 100644
index 00000000000000..87a7c81c534b99
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_copy.pass.cpp
@@ -0,0 +1,38 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_vector& operator=(const inplace_vector& c);
+
+#include <inplace_vector>
+#include <cassert>
+#include "test_macros.h"
+
+constexpr bool tests() {
+ {
+ std::inplace_vector<int, 100> l(3, 2);
+ std::inplace_vector<int, 100> l2(l);
+ l2 = l;
+ assert(l2 == l);
+ }
+ {
+ std::inplace_vector<int, 10> l(3, 2);
+ std::inplace_vector<int, 10> l2;
+ l2 = l;
+ assert(l2 == l);
+ }
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_initializer_list.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_initializer_list.pass.cpp
new file mode 100644
index 00000000000000..a8bfc884267f63
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_initializer_list.pass.cpp
@@ -0,0 +1,77 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// void assign(initializer_list<value_type> il);
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+
+template <typename Vec>
+constexpr void test(Vec& v) {
+ v.assign({3, 4, 5, 6});
+ assert(v.size() == 4);
+ assert(v[0] == 3);
+ assert(v[1] == 4);
+ assert(v[2] == 5);
+ assert(v[3] == 6);
+ v.assign({});
+ assert(v.size() == 0);
+}
+
+constexpr bool tests() {
+ {
+ using V = std::inplace_vector<int, 4>;
+ V d1;
+ V d2{-1, -2};
+ V d3{-1, -2, -3, -4};
+ test(d1);
+ test(d2);
+ test(d3);
+ }
+ {
+ using V = std::inplace_vector<int, 10>;
+ V d1;
+ V d2{-1, -2};
+ V d3{-1, -2, -3, -4};
+ V d4{-1, -2, -3, -4, -6, -7};
+ test(d1);
+ test(d2);
+ test(d3);
+ test(d4);
+ }
+ {
+ using V = std::inplace_vector<int, 100>;
+ V d1;
+ V d2{-1, -2};
+ V d3{-1, -2, -3, -4};
+ V d4{-1, -2, -3, -4, -6, -7};
+ test(d1);
+ test(d2);
+ test(d3);
+ test(d4);
+ }
+ {
+ using V = std::inplace_vector<int, 0>;
+ V d1;
+ d1.assign({});
+ assert(d1.size() == 0);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_iter_iter.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_iter_iter.pass.cpp
new file mode 100644
index 00000000000000..8319fccff40a21
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_iter_iter.pass.cpp
@@ -0,0 +1,119 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// template <class InputIter> void assign(InputIter first, InputIter last);
+
+#include <inplace_vector>
+#include <algorithm>
+#include <cassert>
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "emplace_constructible.h"
+#include "container_test_types.h"
+
+constexpr bool test() {
+ int arr1[] = {42};
+ int arr2[] = {1, 101, 42};
+ if !consteval {
+ using T = EmplaceConstructibleMoveableAndAssignable<int>;
+ using It = forward_iterator<int*>;
+ {
+ std::inplace_vector<T, 10> v;
+ v.assign(It(arr1), It(std::end(arr1)));
+ assert(v[0].value == 42);
+ }
+ {
+ std::inplace_vector<T, 10> v;
+ v.assign(It(arr2), It(std::end(arr2)));
+ assert(v[0].value == 1);
+ assert(v[1].value == 101);
+ assert(v[2].value == 42);
+ }
+ }
+ if !consteval {
+ using T = EmplaceConstructibleMoveableAndAssignable<int>;
+ using It = cpp17_input_iterator<int*>;
+ {
+ std::inplace_vector<T, 10> v;
+ v.assign(It(arr1), It(std::end(arr1)));
+ assert(v[0].copied == 0);
+ assert(v[0].value == 42);
+ }
+ {
+ std::inplace_vector<T, 10> v;
+ v.assign(It(arr2), It(std::end(arr2)));
+ //assert(v[0].copied == 0);
+ assert(v[0].value == 1);
+ //assert(v[1].copied == 0);
+ assert(v[1].value == 101);
+ assert(v[2].copied == 0);
+ assert(v[2].value == 42);
+ }
+ }
+ {
+ using T = int;
+ using It = forward_iterator<int*>;
+ {
+ std::inplace_vector<T, 10> v;
+ v.assign(It(arr1), It(std::end(arr1)));
+ assert(v[0] == 42);
+ }
+ {
+ std::inplace_vector<T, 10> v;
+ v.assign(It(arr2), It(std::end(arr2)));
+ assert(v[0] == 1);
+ assert(v[1] == 101);
+ assert(v[2] == 42);
+ }
+ }
+ {
+ using T = int;
+ using It = cpp17_input_iterator<int*>;
+ {
+ std::inplace_vector<T, 10> v;
+ v.assign(It(arr1), It(std::end(arr1)));
+ assert(v[0] == 42);
+ }
+ {
+ std::inplace_vector<T, 10> v;
+ v.assign(It(arr2), It(std::end(arr2)));
+ assert(v[0] == 1);
+ assert(v[1] == 101);
+ assert(v[2] == 42);
+ }
+ }
+
+ if !consteval {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ try {
+ using It = forward_iterator<int*>;
+
+ std::inplace_vector<int, 10> dst(10);
+ int src[20]{};
+
+ dst.assign(It(src + 0), It(src + 20));
+ assert(false);
+ } catch (const std::bad_alloc& e) {
+ // OK
+ } catch (...) {
+ assert(false);
+ }
+#endif
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_move.addressof.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_move.addressof.compile.pass.cpp
new file mode 100644
index 00000000000000..68063fefe4e614
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_move.addressof.compile.pass.cpp
@@ -0,0 +1,33 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_vector& operator=(vector&& c);
+
+// Validate whether the container can be move-assigned with an ADL-hijacking operator&
+
+#include <inplace_vector>
+#include <utility>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+ {
+ std::inplace_vector<operator_hijacker, 10> vo;
+ std::inplace_vector<operator_hijacker, 10> v;
+ v = std::move(vo);
+ }
+ {
+ std::inplace_vector<operator_hijacker, 0> vo;
+ std::inplace_vector<operator_hijacker, 0> v;
+ v = std::move(vo);
+ }
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_move.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_move.pass.cpp
new file mode 100644
index 00000000000000..e0f7640359122c
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_move.pass.cpp
@@ -0,0 +1,57 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_vector& operator=(inplace_vector&& c);
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "MoveOnly.h"
+
+constexpr bool tests() {
+ if !consteval {
+ std::inplace_vector<MoveOnly, 10> l;
+ std::inplace_vector<MoveOnly, 10> lo;
+ for (int i = 1; i <= 3; ++i) {
+ l.push_back(i);
+ lo.push_back(i);
+ }
+ std::inplace_vector<MoveOnly, 10> l2;
+ l2 = std::move(l);
+ assert(l2.size() == 3);
+ assert(l2[0] == 1);
+ assert(l2[1] == 2);
+ assert(l2[2] == 3);
+ assert(l2 == lo);
+ // assert(l.size() == lo.size()); // l is left unspecified
+ }
+ {
+ std::inplace_vector<int, 10> l;
+ std::inplace_vector<int, 10> lo;
+ for (int i = 1; i <= 3; ++i) {
+ l.push_back(i);
+ lo.push_back(i);
+ }
+ std::inplace_vector<int, 10> l2;
+ l2 = std::move(l);
+ assert(l2 == lo);
+ // assert(l.size() == lo.size()); // l is left unspecified
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_size_value.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_size_value.pass.cpp
new file mode 100644
index 00000000000000..e018e0471c2e3e
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_size_value.pass.cpp
@@ -0,0 +1,47 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// void assign(size_type n, const_reference v);
+
+#include <inplace_vector>
+#include <algorithm>
+#include <cassert>
+
+#include "test_macros.h"
+
+constexpr bool is6(int x) { return x == 6; }
+
+template <typename Vec>
+constexpr void test(Vec& v) {
+ v.assign(5, 6);
+ assert(v.size() == 5);
+ assert(std::all_of(v.begin(), v.end(), is6));
+}
+
+constexpr bool tests() {
+ {
+ using V = std::inplace_vector<int, 10>;
+ V d1;
+ V d2{1, 2, 3, 4, 5, 6, 7, 8};
+ V d3{1, 2, 3};
+ test(d1);
+ test(d2);
+ test(d3);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_default.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_default.pass.cpp
new file mode 100644
index 00000000000000..3573542f888f8b
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_default.pass.cpp
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_vector();
+
+#include <inplace_vector>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "../../../NotConstructible.h"
+
+template <class C>
+constexpr void test0() {
+ static_assert(noexcept(C{}) && noexcept(C()));
+ static_assert(std::is_trivially_default_constructible_v<C> == (C::capacity() == 0));
+ C c;
+ assert(c.empty());
+ C c1 = {};
+ assert(c1.empty());
+}
+
+struct NonTrivial {
+ NonTrivial();
+};
+
+constexpr bool tests() {
+ {
+ using V = std::inplace_vector<int, 0>;
+ test0<V>();
+ constexpr V _;
+ }
+ {
+ using V = std::inplace_vector<int, 10>;
+ test0<V>();
+ constexpr V _;
+ }
+
+ {
+ using V = std::inplace_vector<NotConstructible, 0>;
+ test0<V>();
+ constexpr V _;
+ }
+ if !consteval {
+ test0<std::inplace_vector<NotConstructible, 10>>();
+ }
+
+ {
+ using V = std::inplace_vector<NonTrivial, 0>;
+ test0<V>();
+ constexpr V _;
+ }
+ if !consteval {
+ test0<std::inplace_vector<NonTrivial, 10>>();
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_from_range.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_from_range.pass.cpp
new file mode 100644
index 00000000000000..fdb8ec9a79ddff
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_from_range.pass.cpp
@@ -0,0 +1,43 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// template<container-compatible-range<T> R>
+// inplace_vector(from_range_t, R&& rg);
+
+#include <inplace_vector>
+
+#include "../../from_range_sequence_containers.h"
+#include "test_macros.h"
+
+// TODO: from_range_sequence_containers.h does not support inplace_vector well because it doesn't have an allocator and has a NTTP
+#if 0
+constexpr bool test() {
+ for_all_iterators_and_allocators<int>([]<class Iter, class Sent, class Alloc>() {
+ test_sequence_container<std::inplace_vector, int, Iter, Sent, Alloc>([](const auto&) {});
+ });
+ test_sequence_container_move_only<std::inplace_vector>();
+
+ return true;
+}
+#endif
+
+int main(int, char**) {
+#if 0
+ static_assert(test_constraints<std::inplace_vector, int, double>());
+ test();
+
+ static_assert(test());
+
+ test_exception_safety_throwing_copy<std::inplace_vector>();
+
+ return 0;
+#endif
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_iter_iter.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_iter_iter.pass.cpp
new file mode 100644
index 00000000000000..fd027183169097
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_iter_iter.pass.cpp
@@ -0,0 +1,177 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// template <class InputIter> inplace_vector(InputIter first, InputIter last);
+
+#include <inplace_vector>
+#include <cassert>
+#include <cstddef>
+
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "emplace_constructible.h"
+#include "container_test_types.h"
+
+template <class C, class Iterator>
+constexpr void test(Iterator first, Iterator last) {
+ {
+ C c(first, last);
+ assert(c.size() == static_cast<std::size_t>(std::distance(first, last)));
+ for (typename C::const_iterator i = c.cbegin(), e = c.cend(); i != e; ++i, ++first)
+ assert(*i == *first);
+ }
+ // Test with an empty range
+ {
+ C c(first, first);
+ assert(c.empty());
+ }
+}
+
+constexpr void basic_test_cases() {
+ int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 1, 0};
+ int* an = a + sizeof(a) / sizeof(a[0]);
+ using V = std::inplace_vector<int, 20>;
+ test<V>(cpp17_input_iterator<const int*>(a), cpp17_input_iterator<const int*>(an));
+ test<V>(forward_iterator<const int*>(a), forward_iterator<const int*>(an));
+ test<V>(bidirectional_iterator<const int*>(a), bidirectional_iterator<const int*>(an));
+ test<V>(random_access_iterator<const int*>(a), random_access_iterator<const int*>(an));
+ test<V>(a, an);
+
+ // Regression test for https://github.com/llvm/llvm-project/issues/46841
+ {
+ V v1({}, forward_iterator<const int*>{});
+ V v2(forward_iterator<const int*>{}, {});
+ }
+
+ if !consteval {
+ volatile int src[] = {1, 2, 3};
+ std::inplace_vector<int, 3> v(src, src + 3);
+ assert(v[0] == 1);
+ assert(v[1] == 2);
+ assert(v[2] == 3);
+ }
+}
+
+constexpr void emplaceable_concept_tests() {
+ int arr1[] = {42};
+ int arr2[] = {1, 101, 42};
+ if !consteval {
+ using T = EmplaceConstructible<int>;
+ using It = forward_iterator<int*>;
+ {
+ std::inplace_vector<T, 10> v(It(arr1), It(std::end(arr1)));
+ assert(v[0].value == 42);
+ }
+ {
+ std::inplace_vector<T, 10> v(It(arr2), It(std::end(arr2)));
+ assert(v[0].value == 1);
+ assert(v[1].value == 101);
+ assert(v[2].value == 42);
+ }
+ }
+
+ if !consteval {
+ using T = EmplaceConstructibleAndMoveInsertable<int>;
+ using It = cpp17_input_iterator<int*>;
+ {
+ std::inplace_vector<T, 10> v(It(arr1), It(std::end(arr1)));
+ assert(v[0].copied == 0);
+ assert(v[0].value == 42);
+ }
+ {
+ std::inplace_vector<T, 10> v(It(arr2), It(std::end(arr2)));
+ //assert(v[0].copied == 0);
+ assert(v[0].value == 1);
+ //assert(v[1].copied == 0);
+ assert(v[1].value == 101);
+ assert(v[2].copied == 0);
+ assert(v[2].value == 42);
+ }
+ }
+}
+
+constexpr void overcapacity_tests() {
+ if !consteval {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ try {
+ using It = forward_iterator<int*>;
+
+ std::inplace_vector<int, 10> dst(10);
+ int src[20]{};
+
+ dst.assign(It(src + 0), It(src + 20));
+ assert(false);
+ } catch (const std::bad_alloc& e) {
+ // OK
+ } catch (...) {
+ assert(false);
+ }
+#endif
+ }
+}
+
+struct B1 {
+ int x;
+};
+struct B2 {
+ int y;
+};
+struct Der : B1, B2 {
+ int z;
+};
+
+// Initialize a vector with a different value type.
+constexpr void test_ctor_with_different_value_type() {
+ {
+ // Make sure initialization is performed with each element value, not with
+ // a memory blob.
+ float array[3] = {0.0f, 1.0f, 2.0f};
+ TEST_DIAGNOSTIC_PUSH
+ TEST_MSVC_DIAGNOSTIC_IGNORED(4244) // conversion from 'float' to 'int', possible loss of data
+ std::inplace_vector<int, 10> v(array, array + 3);
+ TEST_DIAGNOSTIC_POP
+ assert(v.size() == 3);
+ assert(v[0] == 0);
+ assert(v[1] == 1);
+ assert(v[2] == 2);
+ }
+ {
+ Der z;
+ Der* array[1] = {&z};
+ // Though the types Der* and B2* are very similar, initialization still cannot
+ // be done with `memcpy`.
+ std::inplace_vector<B2*, 10> v(array, array + 1);
+ assert(v.size() == 1);
+ assert(v[0] == &z);
+ }
+ {
+ // Though the types are different, initialization can be done with `memcpy`.
+ std::int32_t array[1] = {-1};
+ std::inplace_vector<std::uint32_t, 10> v(array, array + 1);
+ assert(v.size() == 1);
+ assert(v[0] == 4294967295U);
+ }
+}
+
+constexpr bool tests() {
+ basic_test_cases();
+ emplaceable_concept_tests(); // See PR34898
+ test_ctor_with_different_value_type();
+ overcapacity_tests();
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_size.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_size.pass.cpp
new file mode 100644
index 00000000000000..cbdcf16d51e91a
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_size.pass.cpp
@@ -0,0 +1,82 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// explicit inplace_vector(size_type n);
+
+#include <vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "DefaultOnly.h"
+#include "min_allocator.h"
+#include "test_allocator.h"
+
+template <class C>
+TEST_CONSTEXPR_CXX20 void
+test(typename C::size_type n, typename C::allocator_type const& a = typename C::allocator_type()) {
+ (void)a;
+ // Test without a custom allocator
+ {
+ C c(n);
+ assert(c.size() == n);
+ assert(c.get_allocator() == typename C::allocator_type());
+#if TEST_STD_VER >= 11
+ for (typename C::const_iterator i = c.cbegin(), e = c.cend(); i != e; ++i)
+ assert(*i == typename C::value_type());
+#endif
+ }
+
+ // Test with a custom allocator
+#if TEST_STD_VER >= 14
+ {
+ C c(n, a);
+ assert(c.size() == n);
+ assert(c.get_allocator() == a);
+ for (typename C::const_iterator i = c.cbegin(), e = c.cend(); i != e; ++i)
+ assert(*i == typename C::value_type());
+ }
+#endif
+}
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+ test<std::vector<int> >(0);
+ test<std::vector<int> >(50);
+#if TEST_STD_VER >= 11
+ test<std::vector<int, min_allocator<int>>>(0);
+ test<std::vector<int, min_allocator<int>>>(50);
+ test<std::vector<int, safe_allocator<int>>>(0);
+ test<std::vector<int, safe_allocator<int>>>(50);
+#endif
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+#if TEST_STD_VER > 17
+ static_assert(tests());
+#endif
+ test<std::vector<DefaultOnly> >(0);
+ test<std::vector<DefaultOnly> >(500);
+ assert(DefaultOnly::count == 0);
+
+#if TEST_STD_VER >= 11
+ test<std::vector<DefaultOnly, min_allocator<DefaultOnly>>>(0);
+ test<std::vector<DefaultOnly, min_allocator<DefaultOnly>>>(500);
+ test<std::vector<DefaultOnly, safe_allocator<DefaultOnly>>>(0);
+ test<std::vector<DefaultOnly, safe_allocator<DefaultOnly>>>(500);
+ test<std::vector<DefaultOnly, test_allocator<DefaultOnly>>>(0, test_allocator<DefaultOnly>(23));
+ test<std::vector<DefaultOnly, test_allocator<DefaultOnly>>>(100, test_allocator<DefaultOnly>(23));
+ assert(DefaultOnly::count == 0);
+#endif
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_size_value.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_size_value.pass.cpp
new file mode 100644
index 00000000000000..60e4d9c880cd3a
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_size_value.pass.cpp
@@ -0,0 +1,60 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_vector(size_type n, const value_type& x);
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+
+template <class C>
+constexpr void test(typename C::size_type n, const typename C::value_type& x) {
+ C c(n, x);
+ assert(c.size() == n);
+ for (typename C::const_iterator i = c.cbegin(), e = c.cend(); i != e; ++i)
+ assert(*i == x);
+}
+
+constexpr bool tests() {
+ test<std::inplace_vector<int, 0>>(0, 3);
+ test<std::inplace_vector<int, 10>>(0, 3);
+ test<std::inplace_vector<int, 100>>(50, 3);
+ test<std::inplace_vector<int, 100>>(100, 3);
+ if !consteval {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ try {
+ std::inplace_vector<int, 10>(50, 3);
+ assert(false);
+ } catch (const std::bad_alloc&) {
+ // OK
+ } catch (...) {
+ assert(false);
+ }
+
+ try {
+ std::inplace_vector<int, 0>(1, 3);
+ assert(false);
+ } catch (const std::bad_alloc&) {
+ // OK
+ } catch (...) {
+ assert(false);
+ }
+#endif
+ }
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/copy.move_only.verify.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/copy.move_only.verify.cpp
new file mode 100644
index 00000000000000..f51899a8ee0e00
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/copy.move_only.verify.cpp
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// Make sure that a std::inplace_vector containing move-only types can't be copied.
+
+#include <inplace_vector>
+
+#include "MoveOnly.h"
+
+void f() {
+ {
+ std::inplace_vector<MoveOnly, 10> v;
+ [[maybe_unused]] std::inplace_vector<MoveOnly, 10> copy =
+ v; // expected-error-re@* {{{{(no matching function for call to 'construct_at')|(call to deleted constructor of 'MoveOnly')}}}}
+ }
+ {
+ std::inplace_vector<MoveOnly, 0> v;
+ // FIXME: This might be ill-formed. It also might be well-formed because it's meant to be trivially copyable.
+ [[maybe_unused]] std::inplace_vector<MoveOnly, 0> copy = v;
+ }
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/copy.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/copy.pass.cpp
new file mode 100644
index 00000000000000..325b80d162102e
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/copy.pass.cpp
@@ -0,0 +1,51 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_vector(const inplace_vector& v);
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+
+template <class C>
+constexpr void test(const C& x) {
+ typename C::size_type s = x.size();
+ C c(x);
+ assert(c.size() == s);
+ assert(c == x);
+}
+
+constexpr bool tests() {
+ {
+ int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 1, 0};
+ constexpr auto a_sz = sizeof(a) / sizeof(a[0]);
+ int* an = a + a_sz;
+ test(std::inplace_vector<int, a_sz>(a, an));
+ test(std::inplace_vector<int, a_sz + 1>(a, an));
+ test(std::inplace_vector<int, a_sz * 2>(a, an));
+ }
+ {
+ // Test copy ctor with empty source
+ std::inplace_vector<int, 10 > v;
+ std::inplace_vector<int, 10> v2 = v;
+ assert(v2 == v);
+ assert(v2.empty());
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/deduct.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/deduct.pass.cpp
new file mode 100644
index 00000000000000..b483b2b9f55939
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/deduct.pass.cpp
@@ -0,0 +1,57 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// No explicit deduction guides. Only implicit copy deduction
+// guide should ever be usable.
+
+// template <class T, size_t N>
+// inplace_vector(inplace_vector<T, N>) -> inplace_vector<T, N>
+
+#include <inplace_vector>
+#include <utility>
+#include <type_traits>
+#include <span>
+
+#include "test_macros.h"
+#include "test_iterators.h"
+
+TEST_CLANG_DIAGNOSTIC_IGNORED("-Wctad-maybe-unsupported")
+
+template <typename T>
+constexpr bool copy_deduction() {
+ static_assert(std::is_same_v<decltype(std::inplace_vector(std::declval<T>())), T>);
+ static_assert(std::is_same_v<decltype(std::inplace_vector(std::declval<const T>())), T>);
+ static_assert(std::is_same_v<decltype(std::inplace_vector(std::declval<T&>())), T>);
+ static_assert(std::is_same_v<decltype(std::inplace_vector(std::declval<const T&>())), T>);
+ static_assert(std::is_same_v<decltype(std::inplace_vector{std::declval<T>()}), T>);
+ static_assert(std::is_same_v<decltype(std::inplace_vector{std::declval<const T>()}), T>);
+ static_assert(std::is_same_v<decltype(std::inplace_vector{std::declval<T&>()}), T>);
+ static_assert(std::is_same_v<decltype(std::inplace_vector{std::declval<const T&>()}), T>);
+ return true;
+}
+
+static_assert(copy_deduction<std::inplace_vector<int, 10>>());
+static_assert(copy_deduction<std::inplace_vector<int, 0>>());
+
+template <class... Args>
+concept NotDeducible = !(
+ requires(Args... args) { std::inplace_vector(std::forward<Args>(args)...); } ||
+ requires(Args... args) { std::inplace_vector{std::forward<Args>(args)...}; });
+
+static_assert(NotDeducible<>);
+static_assert(NotDeducible<int>);
+static_assert(NotDeducible<std::size_t>);
+static_assert(NotDeducible<int*, int*>);
+static_assert(NotDeducible<std::from_range_t, int (&)[10]>);
+static_assert(NotDeducible<std::from_range_t, std::span<int, 10>>);
+static_assert(NotDeducible<std::initializer_list<int>>);
+
+int main(int, char**) { return 0; }
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/default.recursive.empty.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/default.recursive.empty.pass.cpp
new file mode 100644
index 00000000000000..6e07850d24ff16
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/default.recursive.empty.pass.cpp
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// Unlike vector, inplace_vector cannot be used with an incomplete type
+
+#include <inplace_vector>
+
+#include "test_macros.h"
+
+struct X {
+ // FIXME: is this OK?
+ std::inplace_vector<X, 0> q;
+};
+
+int main(int, char**) {
+ [[maybe_unused]] X x;
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/default.recursive.fail.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/default.recursive.fail.cpp
new file mode 100644
index 00000000000000..c2c5fd17e5dc17
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/default.recursive.fail.cpp
@@ -0,0 +1,22 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// Unlike vector, inplace_vector cannot be used with an incomplete type
+
+#include <inplace_vector>
+
+#include "test_macros.h"
+
+struct Y {
+ std::inplace_vector<Y, 10> q;
+};
+
+int main(int, char**) { return 0; }
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/default_noexcept.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/default_noexcept.pass.cpp
new file mode 100644
index 00000000000000..0d66be3148bcc2
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/default_noexcept.pass.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_vector() noexcept
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "MoveOnly.h"
+
+template <typename C>
+constexpr void test() {
+ static_assert(std::is_nothrow_default_constructible_v<C>);
+ ASSERT_NOEXCEPT(C());
+ ASSERT_NOEXCEPT(C{});
+}
+
+constexpr bool tests() {
+ test<std::inplace_vector<int, 10>>();
+ test<std::inplace_vector<int, 0>>();
+ test<std::inplace_vector<MoveOnly, 10>>();
+ test<std::inplace_vector<MoveOnly, 0>>();
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/dtor_noexcept.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/dtor_noexcept.pass.cpp
new file mode 100644
index 00000000000000..6b6286415f1724
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/dtor_noexcept.pass.cpp
@@ -0,0 +1,45 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// ~inplace_vector() // implied noexcept;
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "MoveOnly.h"
+
+constexpr bool tests() {
+ {
+ using C = std::inplace_vector<int, 0>;
+ static_assert(std::is_nothrow_destructible_v<C>);
+ }
+ {
+ using C = std::inplace_vector<int, 10>;
+ static_assert(std::is_nothrow_destructible_v<C>);
+ }
+ {
+ using C = std::inplace_vector<MoveOnly, 0>;
+ static_assert(std::is_nothrow_destructible_v<C>);
+ }
+ {
+ using C = std::inplace_vector<MoveOnly, 10>;
+ static_assert(std::is_nothrow_destructible_v<C>);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/exceptions.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/exceptions.pass.cpp
new file mode 100644
index 00000000000000..d1e539a289ddda
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/exceptions.pass.cpp
@@ -0,0 +1,166 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+// UNSUPPORTED: no-exceptions
+
+// <inplace_vector>
+
+// (bug report: https://llvm.org/PR58392)
+// Check that vector constructors don't leak memory when an operation inside the constructor throws an exception
+
+#include <cstddef>
+#include <memory>
+#include <type_traits>
+#include <inplace_vector>
+
+#include "count_new.h"
+#include "test_iterators.h"
+
+struct ThrowingT {
+ int* throw_after_n_ = nullptr;
+ ThrowingT() { throw 0; }
+
+ ThrowingT(int& throw_after_n) : throw_after_n_(&throw_after_n) {
+ if (throw_after_n == 0)
+ throw 0;
+ --throw_after_n;
+ }
+
+ ThrowingT(const ThrowingT&) {
+ if (throw_after_n_ == nullptr || *throw_after_n_ == 0)
+ throw 1;
+ --*throw_after_n_;
+ }
+
+ ThrowingT& operator=(const ThrowingT&) {
+ if (throw_after_n_ == nullptr || *throw_after_n_ == 0)
+ throw 1;
+ --*throw_after_n_;
+ return *this;
+ }
+};
+
+template <class IterCat>
+struct Iterator {
+ using iterator_category = IterCat;
+ using difference_type = std::ptrdiff_t;
+ using value_type = int;
+ using reference = int&;
+ using pointer = int*;
+
+ int i_;
+ Iterator(int i = 0) : i_(i) {}
+ int& operator*() {
+ if (i_ == 1)
+ throw 1;
+ return i_;
+ }
+
+ friend bool operator==(const Iterator& lhs, const Iterator& rhs) { return lhs.i_ == rhs.i_; }
+
+ friend bool operator!=(const Iterator& lhs, const Iterator& rhs) { return lhs.i_ != rhs.i_; }
+
+ Iterator& operator++() {
+ ++i_;
+ return *this;
+ }
+
+ Iterator operator++(int) {
+ auto tmp = *this;
+ ++i_;
+ return tmp;
+ }
+};
+
+void check_new_delete_called() {
+ assert(globalMemCounter.new_called == globalMemCounter.delete_called);
+ assert(globalMemCounter.new_array_called == globalMemCounter.delete_array_called);
+ assert(globalMemCounter.aligned_new_called == globalMemCounter.aligned_delete_called);
+ assert(globalMemCounter.aligned_new_array_called == globalMemCounter.aligned_delete_array_called);
+}
+
+int main(int, char**) {
+ try { // Throw in inplace_vector(size_type) from type
+ std::inplace_vector<ThrowingT, 1> v(1);
+ assert(false);
+ } catch (int) {
+ } catch (...) {
+ assert(false);
+ }
+ check_new_delete_called();
+
+ try { // Throw in inplace_vector(size_type) from lack of capacity
+ std::inplace_vector<ThrowingT, 1> v(2);
+ assert(false);
+ } catch (const std::bad_alloc&) {
+ } catch (...) {
+ assert(false);
+ }
+ check_new_delete_called();
+
+ try { // Do not throw when none are constructed
+ [[maybe_unused]] std::inplace_vector<ThrowingT, 1> v1(0);
+ [[maybe_unused]] std::inplace_vector<ThrowingT, 0> v2(0);
+ } catch (...) {
+ assert(false);
+ }
+ check_new_delete_called();
+
+ try { // Throw in inplace_vector(size_type, value_type) from type
+ int throw_after = 1;
+ ThrowingT v(throw_after);
+ std::inplace_vector<ThrowingT, 1> vec(1, v);
+ assert(false);
+ } catch (int) {
+ } catch (...) {
+ assert(false);
+ }
+ check_new_delete_called();
+
+ try { // Throw in inplace_vector(InputIterator, InputIterator) from input iterator
+ std::inplace_vector<int, 4> vec((Iterator<std::input_iterator_tag>()), Iterator<std::input_iterator_tag>(2));
+ assert(false);
+ } catch (int) {
+ } catch (...) {
+ assert(false);
+ }
+ check_new_delete_called();
+
+ try { // Throw in inplace_vector(InputIterator, InputIterator) from forward iterator
+ std::inplace_vector<int, 4> vec((Iterator<std::forward_iterator_tag>()), Iterator<std::forward_iterator_tag>(2));
+ assert(false);
+ } catch (int) {
+ } catch (...) {
+ assert(false);
+ }
+ check_new_delete_called();
+
+ try { // Throw in vector(const vector&) from type
+ std::inplace_vector<ThrowingT, 10> vec;
+ int throw_after = 0;
+ vec.emplace_back(throw_after);
+ auto vec2 = vec;
+ assert(false);
+ } catch (int) {
+ } catch (...) {
+ assert(false);
+ }
+ check_new_delete_called();
+
+ try { // Throw in vector(initializer_list<value_type>) from type
+ int throw_after = 1;
+ std::inplace_vector<ThrowingT, 10> vec({ThrowingT(throw_after)});
+ assert(false);
+ } catch (int) {
+ } catch (...) {
+ assert(false);
+ }
+ check_new_delete_called();
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/initializer_list.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/initializer_list.pass.cpp
new file mode 100644
index 00000000000000..922418ba324634
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/initializer_list.pass.cpp
@@ -0,0 +1,51 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_vector(initializer_list<value_type> il);
+
+#include <inplace_vector>
+#include <cassert>
+#include "test_macros.h"
+
+constexpr bool tests() {
+ {
+ std::inplace_vector<int, 10> d = {3, 4, 5, 6};
+ assert(d.size() == 4);
+ assert(d[0] == 3);
+ assert(d[1] == 4);
+ assert(d[2] == 5);
+ assert(d[3] == 6);
+ }
+ {
+ std::inplace_vector<int, 4> d = {3, 4, 5, 6};
+ assert(d.size() == 4);
+ assert(d[0] == 3);
+ assert(d[1] == 4);
+ assert(d[2] == 5);
+ assert(d[3] == 6);
+ }
+ {
+ std::inplace_vector<int, 10> d = std::initializer_list<int>();
+ assert(d.size() == 0);
+ }
+ {
+ std::inplace_vector<int, 0> d = std::initializer_list<int>();
+ assert(d.size() == 0);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move.addressof.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move.addressof.compile.pass.cpp
new file mode 100644
index 00000000000000..06e2cd08e82b5b
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move.addressof.compile.pass.cpp
@@ -0,0 +1,31 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_(inplace_vector&& c);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <inplace_vector>
+#include <utility>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+ {
+ std::inplace_vector<operator_hijacker, 10> vo;
+ [[maybe_unused]] std::inplace_vector<operator_hijacker, 10> v(std::move(vo));
+ }
+ {
+ std::inplace_vector<operator_hijacker, 0> vo;
+ [[maybe_unused]] std::inplace_vector<operator_hijacker, 0> v(std::move(vo));
+ }
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move.pass.cpp
new file mode 100644
index 00000000000000..4d6fddacc654d3
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move.pass.cpp
@@ -0,0 +1,55 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_vector(inplace_vector&&);
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "MoveOnly.h"
+
+constexpr bool tests() {
+ if !consteval {
+ std::inplace_vector<MoveOnly, 10> l;
+ std::inplace_vector<MoveOnly, 10> lo;
+ for (int i = 1; i <= 3; ++i) {
+ l.push_back(i);
+ lo.push_back(i);
+ }
+ std::inplace_vector<MoveOnly, 10> l2 = std::move(l);
+ assert(l2.size() == 3);
+ assert(l2[0] == 1);
+ assert(l2[1] == 2);
+ assert(l2[2] == 3);
+ assert(l2 == lo);
+ // assert(l.size() == lo.size()); // l is left unspecified
+ }
+ {
+ std::inplace_vector<int, 10> l;
+ std::inplace_vector<int, 10> lo;
+ for (int i = 1; i <= 3; ++i) {
+ l.push_back(i);
+ lo.push_back(i);
+ }
+ std::inplace_vector<int, 10> l2 = std::move(l);
+ assert(l2 == lo);
+ // assert(l.size() == lo.size()); // l is left unspecified
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move_assign_noexcept.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move_assign_noexcept.pass.cpp
new file mode 100644
index 00000000000000..45f74f82c46756
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move_assign_noexcept.pass.cpp
@@ -0,0 +1,51 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_vector& operator=(inplace_vector&& c)
+// noexcept(
+// N == 0 || (is_nothrow_move_assignable_v<T> &&
+// is_nothrow_move_constructible_v<T>));
+
+#include <inplace_vector>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+template <bool ConstructNoexcept, bool AssignNoexcept>
+struct MoveOnly {
+ MoveOnly(MoveOnly&&) noexcept(ConstructNoexcept);
+ MoveOnly& operator=(MoveOnly&&) noexcept(AssignNoexcept);
+ ~MoveOnly();
+};
+
+struct Immovable {
+ Immovable(Immovable&&) = delete;
+ Immovable& operator=(Immovable&&) = delete;
+ ~Immovable();
+};
+
+int main(int, char**) {
+ static_assert(std::is_nothrow_move_assignable_v<std::inplace_vector<int, 0>>);
+ static_assert(std::is_nothrow_move_assignable_v<std::inplace_vector<int, 10>>);
+ static_assert(std::is_nothrow_move_assignable_v<std::inplace_vector<MoveOnly<true, true>, 0>>);
+ static_assert(std::is_nothrow_move_assignable_v<std::inplace_vector<MoveOnly<true, true>, 10>>);
+ static_assert(std::is_nothrow_move_assignable_v<std::inplace_vector<MoveOnly<true, false>, 0>>);
+ static_assert(!std::is_nothrow_move_assignable_v<std::inplace_vector<MoveOnly<true, false>, 10>>);
+ static_assert(std::is_nothrow_move_assignable_v<std::inplace_vector<MoveOnly<false, true>, 0>>);
+ static_assert(!std::is_nothrow_move_assignable_v<std::inplace_vector<MoveOnly<false, true>, 10>>);
+ static_assert(std::is_nothrow_move_assignable_v<std::inplace_vector<MoveOnly<false, false>, 0>>);
+ static_assert(!std::is_nothrow_move_assignable_v<std::inplace_vector<MoveOnly<false, false>, 10>>);
+ static_assert(std::is_nothrow_move_assignable_v<std::inplace_vector<Immovable, 0>>);
+ static_assert(!std::is_nothrow_move_assignable_v<std::inplace_vector<Immovable, 10>>);
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move_noexcept.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move_noexcept.pass.cpp
new file mode 100644
index 00000000000000..54fd549b4719ad
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move_noexcept.pass.cpp
@@ -0,0 +1,49 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_vector(inplace_vector&&)
+// noexcept(N == 0 || is_nothrow_move_assignable_v<T>);
+
+#include <inplace_vector>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+template <bool ConstructNoexcept, bool AssignNoexcept>
+struct MoveOnly {
+ MoveOnly(MoveOnly&&) noexcept(ConstructNoexcept);
+ MoveOnly& operator=(MoveOnly&&) noexcept(AssignNoexcept);
+ ~MoveOnly();
+};
+
+struct Immovable {
+ Immovable(Immovable&&) = delete;
+ Immovable& operator=(Immovable&&) = delete;
+ ~Immovable();
+};
+
+int main(int, char**) {
+ static_assert(std::is_nothrow_move_constructible_v<std::inplace_vector<int, 0>>);
+ static_assert(std::is_nothrow_move_constructible_v<std::inplace_vector<int, 10>>);
+ static_assert(std::is_nothrow_move_constructible_v<std::inplace_vector<MoveOnly<true, true>, 0>>);
+ static_assert(std::is_nothrow_move_constructible_v<std::inplace_vector<MoveOnly<true, true>, 10>>);
+ static_assert(std::is_nothrow_move_constructible_v<std::inplace_vector<MoveOnly<true, false>, 0>>);
+ static_assert(std::is_nothrow_move_constructible_v<std::inplace_vector<MoveOnly<true, false>, 10>>);
+ static_assert(std::is_nothrow_move_constructible_v<std::inplace_vector<MoveOnly<false, true>, 0>>);
+ static_assert(!std::is_nothrow_move_constructible_v<std::inplace_vector<MoveOnly<false, true>, 10>>);
+ static_assert(std::is_nothrow_move_constructible_v<std::inplace_vector<MoveOnly<false, false>, 0>>);
+ static_assert(!std::is_nothrow_move_constructible_v<std::inplace_vector<MoveOnly<false, false>, 10>>);
+ static_assert(std::is_nothrow_move_constructible_v<std::inplace_vector<Immovable, 0>>);
+ static_assert(!std::is_nothrow_move_constructible_v<std::inplace_vector<Immovable, 10>>);
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/op_equal_initializer_list.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/op_equal_initializer_list.pass.cpp
new file mode 100644
index 00000000000000..e78c4969507137
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/op_equal_initializer_list.pass.cpp
@@ -0,0 +1,56 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_vector& operator=(initializer_list<value_type> il);
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+
+constexpr bool tests() {
+ {
+ std::inplace_vector<int, 10> d;
+ d = {3, 4, 5, 6};
+ assert(d.size() == 4);
+ assert(d[0] == 3);
+ assert(d[1] == 4);
+ assert(d[2] == 5);
+ assert(d[3] == 6);
+ }
+ {
+ std::inplace_vector<int, 4> d;
+ d = {3, 4, 5, 6};
+ assert(d.size() == 4);
+ assert(d[0] == 3);
+ assert(d[1] == 4);
+ assert(d[2] == 5);
+ assert(d[3] == 6);
+ }
+ {
+ std::inplace_vector<int, 10> d;
+ d = {};
+ assert(d.size() == 0);
+ }
+ {
+ std::inplace_vector<int, 0> d;
+ d = {};
+ assert(d.size() == 0);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.data/data.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.data/data.pass.cpp
new file mode 100644
index 00000000000000..97e17f4df34713
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.data/data.pass.cpp
@@ -0,0 +1,91 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// pointer data() noexcept;
+
+#include <inplace_vector>
+#include <concepts>
+#include <memory>
+#include <cassert>
+
+#include "test_macros.h"
+
+struct Nasty {
+ constexpr Nasty() : i_(0) {}
+ constexpr Nasty(int i) : i_(i) {}
+ constexpr Nasty(const Nasty& other) : i_(other.i_) {}
+ constexpr Nasty& operator=(const Nasty& other) {
+ i_ = other.i_;
+ return *this;
+ }
+ constexpr ~Nasty() {}
+
+ Nasty* operator&() const {
+ assert(false);
+ return nullptr;
+ }
+ int i_;
+};
+
+std::inplace_vector<Nasty, 10> glob{123};
+
+constexpr bool tests() {
+ {
+ std::inplace_vector<int, 0> v;
+ ASSERT_NOEXCEPT(v.data());
+ assert(v.data() == nullptr);
+ static_assert(v.data() == nullptr);
+ }
+ {
+ std::inplace_vector<int, 10> v;
+ ASSERT_NOEXCEPT(v.data());
+ assert(v.data() == std::to_address(v.begin()));
+ std::same_as<int*> decltype(auto) data = v.data();
+ v.push_back(4);
+ assert(data == std::addressof(v.front()));
+ assert(v.data() == data);
+ assert(data[0] == 4);
+ data[0] = 3;
+ assert(v.front() == 3);
+ }
+ {
+ std::inplace_vector<Nasty, 0> v;
+ ASSERT_NOEXCEPT(v.data());
+ assert(v.data() == nullptr);
+ static_assert(v.data() == nullptr);
+ }
+ if !consteval {
+ std::inplace_vector<Nasty, 10> v;
+ ASSERT_NOEXCEPT(v.data());
+ assert(v.data() == std::to_address(v.begin()));
+ std::same_as<Nasty*> decltype(auto) data = v.data();
+ v.push_back(4);
+ assert(data == std::addressof(v.front()));
+ assert(v.data() == data);
+ assert(data[0].i_ == 4);
+ data[0].i_ = 3;
+ assert(v.front().i_ == 3);
+ }
+ if !consteval {
+ static_assert(glob.data() != nullptr);
+ assert(glob.data()[0].i_ == 123);
+ glob.data()[0].i_ = 321;
+ assert(glob.front().i_ == 321);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.data/data_const.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.data/data_const.pass.cpp
new file mode 100644
index 00000000000000..cf1df0b3b3e210
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.data/data_const.pass.cpp
@@ -0,0 +1,94 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// const_pointer data() const noexcept;
+
+#include <inplace_vector>
+#include <concepts>
+#include <memory>
+#include <utility>
+#include <cassert>
+
+#include "test_macros.h"
+
+struct Nasty {
+ constexpr Nasty() : i_(0) {}
+ constexpr Nasty(int i) : i_(i) {}
+ constexpr Nasty(const Nasty& other) : i_(other.i_) {}
+ constexpr Nasty& operator=(const Nasty& other) {
+ i_ = other.i_;
+ return *this;
+ }
+ constexpr ~Nasty() {}
+
+ Nasty* operator&() const {
+ assert(false);
+ return nullptr;
+ }
+ int i_;
+};
+
+std::inplace_vector<Nasty, 10> glob{123};
+
+constexpr bool tests() {
+ {
+ std::inplace_vector<int, 0> v;
+ ASSERT_NOEXCEPT(std::as_const(v).data());
+ assert(std::as_const(v).data() == nullptr);
+ static_assert(std::as_const(v).data() == nullptr);
+ }
+ {
+ std::inplace_vector<int, 10> v;
+ ASSERT_NOEXCEPT(std::as_const(v).data());
+ assert(std::as_const(v).data() == v.data());
+ assert(std::as_const(v).data() == std::to_address(std::as_const(v).begin()));
+ std::same_as<const int*> decltype(auto) data = std::as_const(v).data();
+ v.push_back(4);
+ assert(data == std::addressof(v.front()));
+ assert(std::as_const(v).data() == data);
+ assert(data[0] == 4);
+ const_cast<int*>(data)[0] = 3;
+ assert(v.front() == 3);
+ }
+ {
+ std::inplace_vector<Nasty, 0> v;
+ ASSERT_NOEXCEPT(std::as_const(v).data());
+ assert(std::as_const(v).data() == nullptr);
+ static_assert(std::as_const(v).data() == nullptr);
+ }
+ if !consteval {
+ std::inplace_vector<Nasty, 10> v;
+ ASSERT_NOEXCEPT(std::as_const(v).data());
+ assert(std::as_const(v).data() == v.data());
+ assert(std::as_const(v).data() == std::to_address(v.begin()));
+ std::same_as<const Nasty*> decltype(auto) data = std::as_const(v).data();
+ v.push_back(4);
+ assert(data == std::addressof(v.front()));
+ assert(std::as_const(v).data() == data);
+ assert(data[0].i_ == 4);
+ const_cast<Nasty*>(data)[0].i_ = 3;
+ assert(v.front().i_ == 3);
+ }
+ if !consteval {
+ static_assert(std::as_const(glob).data() != nullptr);
+ assert(std::as_const(glob).data()[0].i_ == 123);
+ const_cast<Nasty*>(std::as_const(glob).data())[0].i_ = 321;
+ assert(glob.front().i_ == 321);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.erasure/erase.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.erasure/erase.pass.cpp
new file mode 100644
index 00000000000000..fa89dd944ae98f
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.erasure/erase.pass.cpp
@@ -0,0 +1,95 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// template <class T, size_t N, class U>
+// typename inplace_vector<T, N>::size_type
+// erase(inplace_vector<T, N>& c, const U& value);
+
+#include <inplace_vector>
+#include <optional>
+#include <cassert>
+
+#include "test_macros.h"
+
+template <class S, class U>
+constexpr void test0(S s, U val, S expected, std::size_t expected_erased_count) {
+ ASSERT_SAME_TYPE(typename S::size_type, decltype(std::erase(s, val)));
+ assert(expected_erased_count == std::erase(s, val));
+ assert(s == expected);
+}
+
+template <class T, std::size_t N>
+constexpr void test1() {
+ using S = std::inplace_vector<T, N>;
+
+ test0(S(), 1, S(), 0);
+
+ if constexpr (S::capacity() >= 1) {
+ test0(S({1}), 1, S(), 1);
+ test0(S({1}), 2, S({1}), 0);
+ }
+
+ if constexpr (S::capacity() >= 2) {
+ test0(S({1, 2}), 1, S({2}), 1);
+ test0(S({1, 2}), 2, S({1}), 1);
+ test0(S({1, 2}), 3, S({1, 2}), 0);
+ test0(S({1, 1}), 1, S(), 2);
+ test0(S({1, 1}), 3, S({1, 1}), 0);
+ }
+
+ if constexpr (S::capacity() >= 3) {
+ test0(S({1, 2, 3}), 1, S({2, 3}), 1);
+ test0(S({1, 2, 3}), 2, S({1, 3}), 1);
+ test0(S({1, 2, 3}), 3, S({1, 2}), 1);
+ test0(S({1, 2, 3}), 4, S({1, 2, 3}), 0);
+
+ test0(S({1, 1, 1}), 1, S(), 3);
+ test0(S({1, 1, 1}), 2, S({1, 1, 1}), 0);
+ test0(S({1, 1, 2}), 1, S({2}), 2);
+ test0(S({1, 1, 2}), 2, S({1, 1}), 1);
+ test0(S({1, 1, 2}), 3, S({1, 1, 2}), 0);
+ test0(S({1, 2, 2}), 1, S({2, 2}), 1);
+ test0(S({1, 2, 2}), 2, S({1}), 2);
+ test0(S({1, 2, 2}), 3, S({1, 2, 2}), 0);
+ }
+
+ // Test cross-type erasure
+ using opt = std::optional<typename S::value_type>;
+ test0(S(), opt(), S(), 0);
+ if constexpr (S::capacity() >= 3) {
+ test0(S({1, 2, 1}), opt(), S({1, 2, 1}), 0);
+ test0(S({1, 2, 1}), opt(1), S({2}), 2);
+ test0(S({1, 2, 1}), opt(2), S({1, 1}), 1);
+ test0(S({1, 2, 1}), opt(3), S({1, 2, 1}), 0);
+ }
+}
+
+template <class T>
+constexpr void test2() {
+ test1<T, 0>();
+ test1<T, 3>();
+ test1<T, 10>();
+ test1<T, 100>();
+}
+
+constexpr bool tests() {
+ test2<int>();
+ test2<long>();
+ test2<double>();
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.erasure/erase_if.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.erasure/erase_if.pass.cpp
new file mode 100644
index 00000000000000..3642bc71dce468
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.erasure/erase_if.pass.cpp
@@ -0,0 +1,94 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// template <class T, size_t N, class Predicate>
+// typename inplace_vector<T, N>::size_type
+// erase_if(inplace_vector<T, N>& c, Predicate pred);
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+
+template <class S, class Pred>
+constexpr void test0(S s, Pred p, S expected, std::size_t expected_erased_count) {
+ ASSERT_SAME_TYPE(typename S::size_type, decltype(std::erase_if(s, p)));
+ assert(expected_erased_count == std::erase_if(s, p));
+ assert(s == expected);
+}
+
+template <class T, std::size_t N>
+constexpr void test1() {
+ using S = std::inplace_vector<T, N>;
+
+ auto is1 = [](auto v) { return v == 1; };
+ auto is2 = [](auto v) { return v == 2; };
+ auto is3 = [](auto v) { return v == 3; };
+ auto is4 = [](auto v) { return v == 4; };
+ auto True = [](auto) { return true; };
+ auto False = [](auto) { return false; };
+
+ test0(S(), is1, S(), 0);
+
+ if constexpr (S::capacity() >= 1) {
+ test0(S({1}), is1, S(), 1);
+ test0(S({1}), is2, S({1}), 0);
+ }
+
+ if constexpr (S::capacity() >= 2) {
+ test0(S({1, 2}), is1, S({2}), 1);
+ test0(S({1, 2}), is2, S({1}), 1);
+ test0(S({1, 2}), is3, S({1, 2}), 0);
+ test0(S({1, 1}), is1, S(), 2);
+ test0(S({1, 1}), is3, S({1, 1}), 0);
+ }
+
+ if constexpr (S::capacity() >= 3) {
+ test0(S({1, 2, 3}), is1, S({2, 3}), 1);
+ test0(S({1, 2, 3}), is2, S({1, 3}), 1);
+ test0(S({1, 2, 3}), is3, S({1, 2}), 1);
+ test0(S({1, 2, 3}), is4, S({1, 2, 3}), 0);
+
+ test0(S({1, 1, 1}), is1, S(), 3);
+ test0(S({1, 1, 1}), is2, S({1, 1, 1}), 0);
+ test0(S({1, 1, 2}), is1, S({2}), 2);
+ test0(S({1, 1, 2}), is2, S({1, 1}), 1);
+ test0(S({1, 1, 2}), is3, S({1, 1, 2}), 0);
+ test0(S({1, 2, 2}), is1, S({2, 2}), 1);
+ test0(S({1, 2, 2}), is2, S({1}), 2);
+ test0(S({1, 2, 2}), is3, S({1, 2, 2}), 0);
+
+ test0(S({1, 2, 3}), True, S(), 3);
+ test0(S({1, 2, 3}), False, S({1, 2, 3}), 0);
+ }
+}
+
+template <class T>
+constexpr void test2() {
+ test1<T, 0>();
+ test1<T, 3>();
+ test1<T, 10>();
+ test1<T, 100>();
+}
+
+constexpr bool tests() {
+ test2<int>();
+ test2<long>();
+ test2<double>();
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 00000000000000..f56ca34ce7fe36
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,97 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// iterator, const_iterator, reverse_iterator, const_reverse_iterator
+
+#include <inplace_vector>
+
+#include <iterator>
+
+template <typename T, std::size_t N>
+void test() {
+ using V = std::inplace_vector<T, N>;
+ using iterator = typename V::iterator;
+ using const_iterator = typename V::const_iterator;
+ using reverse_iterator = typename V::reverse_iterator;
+ using const_reverse_iterator = typename V::const_reverse_iterator;
+ using value_type = T;
+
+ static_assert(std::contiguous_iterator<iterator>);
+ static_assert(std::random_access_iterator<reverse_iterator>);
+ static_assert(!std::contiguous_iterator<reverse_iterator>);
+ static_assert(std::indirectly_writable<iterator, value_type>);
+ static_assert(std::sentinel_for<iterator, iterator>);
+ static_assert(std::sentinel_for<iterator, const_iterator>);
+ static_assert(!std::sentinel_for<iterator, reverse_iterator>);
+ static_assert(!std::sentinel_for<iterator, const_reverse_iterator>);
+ static_assert(std::sized_sentinel_for<iterator, iterator>);
+ static_assert(std::sized_sentinel_for<iterator, const_iterator>);
+ static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
+ static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
+ static_assert(std::indirectly_movable<iterator, iterator>);
+ static_assert(std::indirectly_movable_storable<iterator, iterator>);
+ static_assert(!std::indirectly_movable<iterator, const_iterator>);
+ static_assert(!std::indirectly_movable_storable<iterator, const_iterator>);
+ static_assert(std::indirectly_movable<iterator, reverse_iterator>);
+ static_assert(std::indirectly_movable_storable<iterator, reverse_iterator>);
+ static_assert(!std::indirectly_movable<iterator, const_reverse_iterator>);
+ static_assert(!std::indirectly_movable_storable<iterator, const_reverse_iterator>);
+ static_assert(std::indirectly_copyable<iterator, iterator>);
+ static_assert(std::indirectly_copyable_storable<iterator, iterator>);
+ static_assert(!std::indirectly_copyable<iterator, const_iterator>);
+ static_assert(!std::indirectly_copyable_storable<iterator, const_iterator>);
+ static_assert(std::indirectly_copyable<iterator, reverse_iterator>);
+ static_assert(std::indirectly_copyable_storable<iterator, reverse_iterator>);
+ static_assert(!std::indirectly_copyable<iterator, const_reverse_iterator>);
+ static_assert(!std::indirectly_copyable_storable<iterator, const_reverse_iterator>);
+ static_assert(std::indirectly_swappable<iterator, iterator>);
+
+ static_assert(std::contiguous_iterator<const_iterator>);
+ static_assert(std::random_access_iterator<const_reverse_iterator>);
+ static_assert(!std::contiguous_iterator<const_reverse_iterator>);
+ static_assert(!std::indirectly_writable<const_iterator, value_type>);
+ static_assert(std::sentinel_for<const_iterator, iterator>);
+ static_assert(std::sentinel_for<const_iterator, const_iterator>);
+ static_assert(!std::sentinel_for<const_iterator, reverse_iterator>);
+ static_assert(!std::sentinel_for<const_iterator, const_reverse_iterator>);
+ static_assert(std::sized_sentinel_for<const_iterator, iterator>);
+ static_assert(std::sized_sentinel_for<const_iterator, const_iterator>);
+ static_assert(!std::sized_sentinel_for<const_iterator, reverse_iterator>);
+ static_assert(!std::sized_sentinel_for<const_iterator, const_reverse_iterator>);
+ static_assert(std::indirectly_movable<const_iterator, iterator>);
+ static_assert(std::indirectly_movable_storable<const_iterator, iterator>);
+ static_assert(!std::indirectly_movable<const_iterator, const_iterator>);
+ static_assert(!std::indirectly_movable_storable<const_iterator, const_iterator>);
+ static_assert(std::indirectly_movable<const_iterator, reverse_iterator>);
+ static_assert(std::indirectly_movable_storable<const_iterator, reverse_iterator>);
+ static_assert(!std::indirectly_movable<const_iterator, const_reverse_iterator>);
+ static_assert(!std::indirectly_movable_storable<const_iterator, const_reverse_iterator>);
+ static_assert(std::indirectly_copyable<const_iterator, iterator>);
+ static_assert(std::indirectly_copyable_storable<const_iterator, iterator>);
+ static_assert(!std::indirectly_copyable<const_iterator, const_iterator>);
+ static_assert(!std::indirectly_copyable_storable<const_iterator, const_iterator>);
+ static_assert(std::indirectly_copyable<const_iterator, reverse_iterator>);
+ static_assert(std::indirectly_copyable_storable<const_iterator, reverse_iterator>);
+ static_assert(!std::indirectly_copyable<const_iterator, const_reverse_iterator>);
+ static_assert(!std::indirectly_copyable_storable<const_iterator, const_reverse_iterator>);
+ static_assert(!std::indirectly_swappable<const_iterator, const_iterator>);
+}
+
+struct NonTrivial {
+ int i = 0;
+};
+
+void tests() {
+ test<int, 0>();
+ test<int, 10>();
+ test<NonTrivial, 0>();
+ test<NonTrivial, 10>();
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/iterators.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/iterators.pass.cpp
new file mode 100644
index 00000000000000..22e87d064ac4f2
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/iterators.pass.cpp
@@ -0,0 +1,198 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// iterator begin() noexcept;
+// iterator end() noexcept;
+// const_iterator begin() const noexcept;
+// const_iterator end() const noexcept;
+// const_iterator cbegin() const noexcept;
+// const_iterator cend() const noexcept;
+
+#include <inplace_vector>
+#include <cassert>
+#include <iterator>
+
+#include "test_macros.h"
+
+struct A {
+ int first;
+ int second;
+};
+
+constexpr bool tests() {
+ {
+ using C = std::inplace_vector<int, 0>;
+ C c;
+ std::same_as<C::iterator> decltype(auto) i = c.begin();
+ C::iterator j = c.end();
+ assert(std::distance(i, j) == 0);
+ assert(i == j);
+ }
+ {
+ using C = std::inplace_vector<int, 10>;
+ C c;
+ std::same_as<C::iterator> decltype(auto) i = c.begin();
+ C::iterator j = c.end();
+ assert(std::distance(i, j) == 0);
+ assert(i == j);
+ }
+ {
+ using C = std::inplace_vector<int, 0>;
+ const C c;
+ std::same_as<C::const_iterator> decltype(auto) i = c.begin();
+ C::const_iterator j = c.end();
+ assert(std::distance(i, j) == 0);
+ assert(i == j);
+ }
+ {
+ using C = std::inplace_vector<int, 10>;
+ const C c;
+ std::same_as<C::const_iterator> decltype(auto) i = c.begin();
+ C::const_iterator j = c.end();
+ assert(std::distance(i, j) == 0);
+ assert(i == j);
+ }
+ {
+ using C = std::inplace_vector<int, 10>;
+ C c;
+ std::same_as<C::const_iterator> decltype(auto) i = c.cbegin();
+ C::const_iterator j = c.cend();
+ assert(std::distance(i, j) == 0);
+ assert(i == j);
+ assert(i == c.end());
+ }
+ {
+ using C = std::inplace_vector<int, 10>;
+ const int t[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ C c(std::begin(t), std::end(t));
+ C::iterator i = c.begin();
+ assert(*i == 0);
+ ++i;
+ assert(*i == 1);
+ *i = 10;
+ assert(*i == 10);
+ assert(std::distance(c.begin(), c.end()) == 10);
+ }
+ {
+ using C = std::inplace_vector<int, 10>;
+ [[maybe_unused]] C::iterator i;
+ [[maybe_unused]] C::const_iterator j;
+ C::iterator i2{};
+ C::iterator i3 = i2;
+ C::const_iterator j2{};
+ C::const_iterator j3 = i2;
+ C::const_iterator j4 = j2;
+ assert(i2 == j2);
+ j4 = j3;
+ j2 = i2;
+ i2 = i3;
+ }
+ {
+ using C = std::inplace_vector<int, 10>;
+ C c;
+ C::iterator i = c.begin();
+ C::iterator j = c.end();
+ assert(std::distance(i, j) == 0);
+
+ assert(i == j);
+ assert(!(i != j));
+
+ assert(!(i < j));
+ assert((i <= j));
+
+ assert(!(i > j));
+ assert((i >= j));
+
+ std::same_as<std::strong_ordering> decltype(auto) r1 = i <=> j;
+ assert(r1 == std::strong_ordering::equal);
+ }
+ {
+ using C = std::inplace_vector<int, 10>;
+ const C c;
+ C::const_iterator i = c.begin();
+ C::const_iterator j = c.end();
+ assert(std::distance(i, j) == 0);
+
+ assert(i == j);
+ assert(!(i != j));
+
+ assert(!(i < j));
+ assert((i <= j));
+
+ assert(!(i > j));
+ assert((i >= j));
+
+ std::same_as<std::strong_ordering> decltype(auto) r1 = i <=> j;
+ assert(r1 == std::strong_ordering::equal);
+ }
+ {
+ using C = std::inplace_vector<int, 10>;
+ const int t[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ C c(std::begin(t), std::end(t));
+ C::iterator i = c.begin();
+ C::iterator j = i;
+ assert(*i == 0);
+ ++i;
+ assert(*i == 1);
+ *i = 10;
+ assert(*i == 10);
+ assert(j == c.begin());
+ assert(++j == i);
+ assert(std::distance(c.begin(), c.end()) == 10);
+ }
+ {
+ using C = std::inplace_vector<A, 10>;
+ C c = {A{1, 2}};
+ C::iterator i = c.begin();
+ i->first = 3;
+ C::const_iterator j = i;
+ assert(j->first == 3);
+ }
+ {
+ using C = std::inplace_vector<int, 10>;
+ C::iterator ii1{}, ii2{};
+ C::iterator ii4 = ii1;
+ C::const_iterator cii{};
+ assert(ii1 == ii2);
+ assert(ii1 == ii4);
+
+ assert(!(ii1 != ii2));
+
+ assert((ii1 == cii));
+ assert((cii == ii1));
+ assert(!(ii1 != cii));
+ assert(!(cii != ii1));
+ assert(!(ii1 < cii));
+ assert(!(cii < ii1));
+ assert((ii1 <= cii));
+ assert((cii <= ii1));
+ assert(!(ii1 > cii));
+ assert(!(cii > ii1));
+ assert((ii1 >= cii));
+ assert((cii >= ii1));
+ assert(cii - ii1 == 0);
+ assert(ii1 - cii == 0);
+
+ std::same_as<std::strong_ordering> decltype(auto) r1 = ii1 <=> ii2;
+ assert(r1 == std::strong_ordering::equal);
+
+ std::same_as<std::strong_ordering> decltype(auto) r2 = cii <=> ii2;
+ assert(r2 == std::strong_ordering::equal);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/range_concept_conformance.compile.pass.cpp
new file mode 100644
index 00000000000000..292affbafc4d59
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/range_concept_conformance.compile.pass.cpp
@@ -0,0 +1,48 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_vector
+
+#include <inplace_vector>
+
+#include <concepts>
+#include <ranges>
+#include "MoveOnly.h"
+
+template <typename T, std::size_t N>
+void test() {
+ using range = std::inplace_vector<T, N>;
+
+ static_assert(std::same_as<std::ranges::iterator_t<range>, typename range::iterator>);
+ static_assert(std::ranges::common_range<range>);
+ static_assert(std::ranges::random_access_range<range>);
+ static_assert(std::ranges::contiguous_range<range>);
+ static_assert(!std::ranges::view<range>);
+ static_assert(std::ranges::sized_range<range>);
+ static_assert(!std::ranges::borrowed_range<range>);
+ static_assert(std::ranges::viewable_range<range>);
+
+ static_assert(std::same_as<std::ranges::iterator_t<range const>, typename range::const_iterator>);
+ static_assert(std::ranges::common_range<range const>);
+ static_assert(std::ranges::random_access_range<range const>);
+ static_assert(std::ranges::contiguous_range<range const>);
+ static_assert(!std::ranges::view<range const>);
+ static_assert(std::ranges::sized_range<range const>);
+ static_assert(!std::ranges::borrowed_range<range const>);
+ static_assert(!std::ranges::viewable_range<range const>);
+}
+
+void tests() {
+ test<int, 0>();
+ test<int, 10>();
+ test<MoveOnly, 0>();
+ test<MoveOnly, 10>();
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/reverse_iterators.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/reverse_iterators.pass.cpp
new file mode 100644
index 00000000000000..37e83391c3019a
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/reverse_iterators.pass.cpp
@@ -0,0 +1,92 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// reverse_iterator rbegin();
+// reverse_iterator rend();
+// const_reverse_iterator rbegin() const;
+// const_reverse_iterator rend() const;
+// const_reverse_iterator crbegin() const;
+// const_reverse_iterator crend() const;
+
+#include <inplace_vector>
+#include <cassert>
+#include <iterator>
+
+#include "MoveOnly.h"
+
+template <class Vector, bool IsConstexpr>
+constexpr void check_vector_reverse_iterators() {
+ bool ConstexprTests = true;
+ if consteval {
+ ConstexprTests = IsConstexpr;
+ }
+
+ if (ConstexprTests) {
+ Vector vec;
+ assert(vec.rbegin() == vec.rend());
+ assert(vec.crbegin() == vec.crend());
+ }
+ if (ConstexprTests && Vector::capacity() >= 10) {
+ const int n = 10;
+ Vector vec;
+ const Vector& cvec = vec;
+ vec.reserve(n);
+ for (int i = 0; i < n; ++i)
+ vec.push_back(i);
+ {
+ int iterations = 0;
+
+ for (typename Vector::const_reverse_iterator it = vec.crbegin(); it != vec.crend(); ++it) {
+ assert(*it == (n - iterations - 1));
+ ++iterations;
+ }
+ assert(iterations == n);
+ }
+ {
+ assert(cvec.rbegin() == vec.crbegin());
+ assert(cvec.rend() == vec.crend());
+ }
+ {
+ int iterations = 0;
+
+ for (typename Vector::reverse_iterator it = vec.rbegin(); it != vec.rend(); ++it) {
+ assert(*it == (n - iterations - 1));
+ *it = 40;
+ assert(*it == 40);
+ ++iterations;
+ }
+ assert(iterations == n);
+ }
+
+ assert(std::distance(vec.rbegin(), vec.rend()) == n);
+ assert(std::distance(cvec.rbegin(), cvec.rend()) == n);
+ assert(std::distance(vec.crbegin(), vec.crend()) == n);
+ assert(std::distance(cvec.crbegin(), cvec.crend()) == n);
+ }
+}
+
+constexpr bool test() {
+ check_vector_reverse_iterators<std::inplace_vector<int, 0>, true>();
+ check_vector_reverse_iterators<std::inplace_vector<int, 10>, true>();
+ check_vector_reverse_iterators<std::inplace_vector<int, 100>, true>();
+ check_vector_reverse_iterators<std::inplace_vector<MoveOnly, 0>, true>();
+ check_vector_reverse_iterators<std::inplace_vector<MoveOnly, 10>, false>();
+ check_vector_reverse_iterators<std::inplace_vector<MoveOnly, 100>, false>();
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/types.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/types.pass.cpp
new file mode 100644
index 00000000000000..7a6ce7b7cc1dc7
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/types.pass.cpp
@@ -0,0 +1,70 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// Test nested types:
+
+// template <class T, size_t N>
+// class inplace_vector
+// {
+// public:
+// 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;
+// using const_iterator = implementation-defined;
+// using reverse_iterator = std::reverse_iterator<iterator>;
+// using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+// };
+
+#include <inplace_vector>
+#include <iterator>
+#include <type_traits>
+
+#include "test_macros.h"
+#include "../../Copyable.h"
+
+template <class T, size_t N>
+void test() {
+ using C = std::inplace_vector<T, N>;
+ static_assert(std::is_same_v<typename C::value_type, T>);
+ static_assert(std::is_same_v<typename C::size_type, std::size_t>);
+ static_assert(std::is_same_v<typename C::difference_type, std::ptrdiff_t>);
+ static_assert(std::is_same_v<typename C::reference, T&>);
+ static_assert(std::is_same_v<typename C::const_reference, const T&>);
+ static_assert(std::is_same_v<typename C::pointer, T*>);
+ static_assert(std::is_same_v<typename C::const_pointer, const T*>);
+ static_assert(std::is_same_v< typename std::iterator_traits<typename C::iterator>::iterator_category,
+ std::random_access_iterator_tag>);
+ static_assert(std::is_same_v< typename std::iterator_traits<typename C::const_iterator>::iterator_category,
+ std::random_access_iterator_tag>);
+ static_assert(std::contiguous_iterator<typename C::iterator>);
+ static_assert(std::contiguous_iterator<typename C::const_iterator>);
+ static_assert(std::is_same_v<typename C::reverse_iterator, std::reverse_iterator<typename C::iterator>>);
+ static_assert(std::is_same_v<typename C::const_reverse_iterator, std::reverse_iterator<typename C::const_iterator>>);
+}
+
+template <class T>
+void test() {
+ test<T, 0>();
+ test<T, 1>();
+ test<T, 10>();
+ test<T, 100>();
+}
+
+int main(int, char**) {
+ test<int>();
+ test<int*>();
+ test<Copyable>();
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/append_range.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/append_range.pass.cpp
new file mode 100644
index 00000000000000..6eb0ddd1c1f3a7
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/append_range.pass.cpp
@@ -0,0 +1,66 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=2000000
+
+// template<container-compatible-range<T> R>
+// constexpr void append_range(R&& rg); // C++23
+
+#include <vector>
+
+#include "../../insert_range_sequence_containers.h"
+#include "test_macros.h"
+
+// Tested cases:
+// - different kinds of insertions (appending an {empty/one-element/mid-sized/long range} into an
+// {empty/one-element/full} container);
+// - appending move-only elements;
+// - an exception is thrown when copying the elements or when allocating new elements.
+constexpr bool test() {
+ static_assert(test_constraints_append_range<std::vector, int, double>());
+
+ for_all_iterators_and_allocators<int, const int*>([]<class Iter, class Sent, class Alloc>() {
+ test_sequence_append_range<std::vector<int, Alloc>, Iter, Sent>([]([[maybe_unused]] auto&& c) {});
+ });
+ test_sequence_append_range_move_only<std::vector>();
+
+ { // Vector may or may not need to reallocate because of the insertion -- make sure to test both cases.
+ { // Ensure reallocation happens.
+ int in[] = {-1, -2, -3, -4, -5, -6, -7, -8, -9, -10};
+ std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8};
+ v.shrink_to_fit();
+ assert(v.capacity() < v.size() + std::ranges::size(in));
+
+ v.append_range(in);
+ assert(std::ranges::equal(v, std::array{1, 2, 3, 4, 5, 6, 7, 8, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10}));
+ }
+
+ { // Ensure no reallocation happens.
+ int in[] = {-1, -2, -3, -4, -5, -6, -7, -8, -9, -10};
+ std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8};
+ v.reserve(v.size() + std::ranges::size(in));
+ assert(v.capacity() >= v.size() + std::ranges::size(in));
+
+ v.append_range(in);
+ assert(std::ranges::equal(v, std::array{1, 2, 3, 4, 5, 6, 7, 8, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10}));
+ }
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ test_append_range_exception_safety_throwing_copy<std::vector>();
+ test_append_range_exception_safety_throwing_allocator<std::vector, int>();
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/assert.push_back.invalidation.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/assert.push_back.invalidation.pass.cpp
new file mode 100644
index 00000000000000..193c00891da7f0
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/assert.push_back.invalidation.pass.cpp
@@ -0,0 +1,56 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// void push_back(const value_type& x);
+//
+// If no reallocation happens, then references, pointers, and iterators before
+// the insertion point remain valid but those at or after the insertion point,
+// including the past-the-end iterator, are invalidated.
+
+// REQUIRES: has-unix-headers, libcpp-has-abi-bounded-iterators-in-vector
+// UNSUPPORTED: c++03
+// UNSUPPORTED: libcpp-hardening-mode=none
+// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
+
+#include <vector>
+#include <cassert>
+#include <cstddef>
+
+#include "check_assertion.h"
+
+int main(int, char**) {
+ std::vector<int> vec;
+ vec.reserve(4);
+ std::size_t old_capacity = vec.capacity();
+ assert(old_capacity >= 4);
+
+ vec.push_back(0);
+ vec.push_back(1);
+ vec.push_back(2);
+ auto it = vec.begin();
+ vec.push_back(3);
+ assert(vec.capacity() == old_capacity);
+
+ // The capacity did not change, so the iterator remains valid and can reach the new element.
+ assert(*it == 0);
+ assert(*(it + 1) == 1);
+ assert(*(it + 2) == 2);
+ assert(*(it + 3) == 3);
+
+ while (vec.capacity() == old_capacity) {
+ vec.push_back(42);
+ }
+ TEST_LIBCPP_ASSERT_FAILURE(
+ *(it + old_capacity), "__bounded_iter::operator*: Attempt to dereference an iterator at the end");
+ // Unfortunately, the bounded iterator does not detect that it's been invalidated and will still allow attempts to
+ // dereference elements 0 to 3 (even though they refer to memory that's been reallocated).
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/assign_range.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/assign_range.pass.cpp
new file mode 100644
index 00000000000000..8fabbbab3d3685
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/assign_range.pass.cpp
@@ -0,0 +1,74 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=2000000
+
+// template<container-compatible-range<T> R>
+// constexpr void assign_range(R&& rg); // C++23
+
+#include <vector>
+
+#include "../../insert_range_sequence_containers.h"
+#include "test_macros.h"
+
+// Tested cases:
+// - different kinds of assignments (assigning an {empty/one-element/mid-sized/long range} to an
+// {empty/one-element/full} container);
+// - assigning move-only elements;
+// - an exception is thrown when copying the elements or when allocating new elements.
+constexpr bool test() {
+ static_assert(test_constraints_assign_range<std::vector, int, double>());
+
+ for_all_iterators_and_allocators<int, const int*>([]<class Iter, class Sent, class Alloc>() {
+ test_sequence_assign_range<std::vector<int, Alloc>, Iter, Sent>([]([[maybe_unused]] auto&& c) {});
+ });
+ test_sequence_assign_range_move_only<std::vector>();
+
+ { // Vector may or may not need to reallocate because of the assignment -- make sure to test both cases.
+ { // Ensure reallocation happens.
+ int in[] = {-1, -2, -3, -4, -5, -6, -7, -8, -9, -10};
+ std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8};
+ v.shrink_to_fit();
+ assert(v.capacity() < v.size() + std::ranges::size(in));
+
+ v.assign_range(in);
+ assert(std::ranges::equal(v, in));
+ }
+
+ { // Ensure no reallocation happens -- the input range is shorter than the vector.
+ int in[] = {-1, -2, -3, -4, -5};
+ std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8};
+
+ v.assign_range(in);
+ assert(std::ranges::equal(v, in));
+ }
+
+ { // Ensure no reallocation happens -- the input range is longer than the vector but within capacity.
+ int in[] = {-1, -2, -3, -4, -5, -6, -7, -8};
+ std::vector<int> v = {1, 2, 3, 4, 5};
+ v.reserve(std::ranges::size(in));
+ assert(v.capacity() >= std::ranges::size(in));
+
+ v.assign_range(in);
+ assert(std::ranges::equal(v, in));
+ }
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ test_assign_range_exception_safety_throwing_copy<std::vector>();
+ test_assign_range_exception_safety_throwing_allocator<std::vector, int>();
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/clear.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/clear.pass.cpp
new file mode 100644
index 00000000000000..90056fff8d9b56
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/clear.pass.cpp
@@ -0,0 +1,54 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// void clear() noexcept;
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "MoveOnly.h"
+
+constexpr bool tests() {
+ {
+ std::inplace_vector<int, 10> c{1, 2, 3};
+ ASSERT_NOEXCEPT(c.clear());
+ c.clear();
+ assert(c.empty());
+ }
+ {
+ std::inplace_vector<int, 0> c;
+ ASSERT_NOEXCEPT(c.clear());
+ c.clear();
+ assert(c.empty());
+ }
+ {
+ std::inplace_vector<MoveOnly, 0> c;
+ ASSERT_NOEXCEPT(c.clear());
+ c.clear();
+ assert(c.empty());
+ }
+ if !consteval {
+ std::inplace_vector<MoveOnly, 10> c;
+ c.push_back(0);
+ ASSERT_NOEXCEPT(c.clear());
+ c.clear();
+ assert(c.empty());
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/destroy_elements.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/destroy_elements.pass.cpp
new file mode 100644
index 00000000000000..7ef83fb3754c3f
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/destroy_elements.pass.cpp
@@ -0,0 +1,156 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// Ensure that all the elements in the inplace_vector are destroyed
+
+#include <algorithm>
+#include <array>
+#include <cassert>
+#include <vector>
+#include <inplace_vector>
+
+#include "test_macros.h"
+
+struct DestroyTracker {
+ constexpr DestroyTracker(std::vector<bool>& vec) : vec_(&vec), index_(vec.size()) { vec.push_back(false); }
+
+ constexpr DestroyTracker(const DestroyTracker& other) : vec_(other.vec_), index_(vec_->size()) {
+ vec_->push_back(false);
+ }
+
+ constexpr DestroyTracker& operator=(const DestroyTracker&) { return *this; }
+ constexpr ~DestroyTracker() { (*vec_)[index_] = true; }
+
+ std::vector<bool>* vec_;
+ size_t index_;
+};
+
+template <std::size_t N, class Operation>
+constexpr void test(Operation operation) {
+ std::vector<bool> all_destroyed;
+
+ {
+ std::inplace_vector<DestroyTracker, N> v;
+ for (size_t i = 0; i != 100; ++i)
+ operation(v, all_destroyed);
+ }
+
+ assert(std::all_of(all_destroyed.begin(), all_destroyed.end(), [](bool b) { return b; }));
+}
+
+template <typename V>
+constexpr void checked_op(V& vec, std::vector<bool>& tracker, int operation_number) {
+ bool needed = (operation_number < 0) ? 2 : 1;
+ bool has_capacity = vec.capacity() - vec.size() >= needed;
+ if consteval {
+ if (!has_capacity)
+ return; // No exceptions in constant expression
+ }
+#ifdef TEST_HAS_NO_EXCEPTIONS
+ if (!has_capacity)
+ return;
+#else
+ try {
+#endif
+ switch (operation_number) {
+ case 0:
+ vec.emplace_back(tracker);
+ break;
+ case 1:
+ vec.push_back(DestroyTracker(tracker));
+ break;
+ case 2:
+ vec.push_back(static_cast<const DestroyTracker&>(DestroyTracker(tracker)));
+ break;
+ case 3:
+ vec.emplace(vec.begin(), tracker);
+ break;
+ case 4:
+ vec.insert(vec.begin(), DestroyTracker(tracker));
+ break;
+ case 5:
+ vec.insert(vec.begin(), static_cast<const DestroyTracker&>(DestroyTracker(tracker)));
+ break;
+ case -1:
+ vec.insert_range(vec.begin(), std::array<DestroyTracker, 2>{tracker, tracker});
+ break;
+ case -2:
+ vec.append_range(std::array<DestroyTracker, 2>{tracker, tracker});
+ break;
+ }
+ assert(has_capacity);
+#ifndef TEST_HAS_NO_EXCEPTIONS
+}
+catch (const std::bad_alloc&) {
+ assert(!has_capacity);
+}
+catch (...) {
+ assert(false);
+}
+#endif
+}
+
+template <typename V>
+constexpr void single_try_op(V& vec, std::vector<bool>& tracker, int operation_number) {
+ bool needed = (operation_number < 0) ? 2 : 1;
+ bool has_capacity = vec.capacity() - vec.size() > needed;
+
+ switch (operation_number) {
+ case 0:
+ vec.try_emplace_back(tracker);
+ break;
+ case 1:
+ vec.try_push_back(DestroyTracker(tracker));
+ break;
+ case 2:
+ vec.try_push_back(static_cast<const DestroyTracker&>(DestroyTracker(tracker)));
+ break;
+ case 3:
+ vec.try_emplace(vec.begin(), tracker);
+ break;
+ case 4:
+ vec.try_insert(vec.begin(), DestroyTracker(tracker));
+ break;
+ case 5:
+ vec.try_insert(vec.begin(), static_cast<const DestroyTracker&>(DestroyTracker(tracker)));
+ break;
+ case -1:
+ vec.insert_range(vec.begin(), std::array<DestroyTracker, 2>{tracker, tracker});
+ break;
+ case -2:
+ vec.append_range(std::array<DestroyTracker, 2>{tracker, tracker});
+ break;
+ }
+ assert(has_capacity);
+}
+
+template <std::size_t N>
+constexpr bool test() {
+ using V = std::inplace_vector<DestroyTracker, N>;
+ for (int i = -2; i <= 5; ++i) {
+ test<N>([i](V& vec, std::vector<bool>& tracker) { checked_op(vec, tracker, i); });
+ }
+
+ return true;
+}
+
+constexpr bool tests() {
+ test<0>();
+ test<10>();
+ test<100>();
+ return true;
+}
+
+int main() {
+ tests();
+ // inplace_vector does not support constexpr evaluation when type is not trivially destructible
+ // static_assert(tests());
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace.addressof.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace.addressof.compile.pass.cpp
new file mode 100644
index 00000000000000..43e553e71e7414
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace.addressof.compile.pass.cpp
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03 && !stdlib=libc++
+
+// <vector>
+
+// template <class... Args> iterator emplace(const_iterator pos, Args&&... args);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <vector>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+ std::vector<operator_hijacker> v;
+ v.emplace(v.end());
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace.pass.cpp
new file mode 100644
index 00000000000000..31389181b7f820
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace.pass.cpp
@@ -0,0 +1,156 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03 && !stdlib=libc++
+
+// <vector>
+
+// template <class... Args> iterator emplace(const_iterator pos, Args&&... args);
+
+#include <vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+class A {
+ int i_;
+ double d_;
+
+ A(const A&);
+ A& operator=(const A&);
+
+public:
+ TEST_CONSTEXPR_CXX14 A(int i, double d) : i_(i), d_(d) {}
+
+ TEST_CONSTEXPR_CXX14 A(A&& a) : i_(a.i_), d_(a.d_) {
+ a.i_ = 0;
+ a.d_ = 0;
+ }
+
+ TEST_CONSTEXPR_CXX14 A& operator=(A&& a) {
+ i_ = a.i_;
+ d_ = a.d_;
+ a.i_ = 0;
+ a.d_ = 0;
+ return *this;
+ }
+
+ TEST_CONSTEXPR_CXX14 int geti() const { return i_; }
+ TEST_CONSTEXPR_CXX14 double getd() const { return d_; }
+};
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+ {
+ std::vector<A> c;
+ std::vector<A>::iterator i = c.emplace(c.cbegin(), 2, 3.5);
+ assert(i == c.begin());
+ assert(c.size() == 1);
+ assert(c.front().geti() == 2);
+ assert(c.front().getd() == 3.5);
+ i = c.emplace(c.cend(), 3, 4.5);
+ assert(i == c.end() - 1);
+ assert(c.size() == 2);
+ assert(c.front().geti() == 2);
+ assert(c.front().getd() == 3.5);
+ assert(c.back().geti() == 3);
+ assert(c.back().getd() == 4.5);
+ i = c.emplace(c.cbegin() + 1, 4, 6.5);
+ assert(i == c.begin() + 1);
+ assert(c.size() == 3);
+ assert(c.front().geti() == 2);
+ assert(c.front().getd() == 3.5);
+ assert(c[1].geti() == 4);
+ assert(c[1].getd() == 6.5);
+ assert(c.back().geti() == 3);
+ assert(c.back().getd() == 4.5);
+ }
+ {
+ std::vector<A, limited_allocator<A, 7> > c;
+ std::vector<A, limited_allocator<A, 7> >::iterator i = c.emplace(c.cbegin(), 2, 3.5);
+ assert(i == c.begin());
+ assert(c.size() == 1);
+ assert(c.front().geti() == 2);
+ assert(c.front().getd() == 3.5);
+ i = c.emplace(c.cend(), 3, 4.5);
+ assert(i == c.end() - 1);
+ assert(c.size() == 2);
+ assert(c.front().geti() == 2);
+ assert(c.front().getd() == 3.5);
+ assert(c.back().geti() == 3);
+ assert(c.back().getd() == 4.5);
+ i = c.emplace(c.cbegin() + 1, 4, 6.5);
+ assert(i == c.begin() + 1);
+ assert(c.size() == 3);
+ assert(c.front().geti() == 2);
+ assert(c.front().getd() == 3.5);
+ assert(c[1].geti() == 4);
+ assert(c[1].getd() == 6.5);
+ assert(c.back().geti() == 3);
+ assert(c.back().getd() == 4.5);
+ }
+ {
+ std::vector<A, min_allocator<A> > c;
+ std::vector<A, min_allocator<A> >::iterator i = c.emplace(c.cbegin(), 2, 3.5);
+ assert(i == c.begin());
+ assert(c.size() == 1);
+ assert(c.front().geti() == 2);
+ assert(c.front().getd() == 3.5);
+ i = c.emplace(c.cend(), 3, 4.5);
+ assert(i == c.end() - 1);
+ assert(c.size() == 2);
+ assert(c.front().geti() == 2);
+ assert(c.front().getd() == 3.5);
+ assert(c.back().geti() == 3);
+ assert(c.back().getd() == 4.5);
+ i = c.emplace(c.cbegin() + 1, 4, 6.5);
+ assert(i == c.begin() + 1);
+ assert(c.size() == 3);
+ assert(c.front().geti() == 2);
+ assert(c.front().getd() == 3.5);
+ assert(c[1].geti() == 4);
+ assert(c[1].getd() == 6.5);
+ assert(c.back().geti() == 3);
+ assert(c.back().getd() == 4.5);
+ }
+ {
+ std::vector<A, safe_allocator<A> > c;
+ std::vector<A, safe_allocator<A> >::iterator i = c.emplace(c.cbegin(), 2, 3.5);
+ assert(i == c.begin());
+ assert(c.size() == 1);
+ assert(c.front().geti() == 2);
+ assert(c.front().getd() == 3.5);
+ i = c.emplace(c.cend(), 3, 4.5);
+ assert(i == c.end() - 1);
+ assert(c.size() == 2);
+ assert(c.front().geti() == 2);
+ assert(c.front().getd() == 3.5);
+ assert(c.back().geti() == 3);
+ assert(c.back().getd() == 4.5);
+ i = c.emplace(c.cbegin() + 1, 4, 6.5);
+ assert(i == c.begin() + 1);
+ assert(c.size() == 3);
+ assert(c.front().geti() == 2);
+ assert(c.front().getd() == 3.5);
+ assert(c[1].geti() == 4);
+ assert(c[1].getd() == 6.5);
+ assert(c.back().geti() == 3);
+ assert(c.back().getd() == 4.5);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+#if TEST_STD_VER > 17
+ static_assert(tests());
+#endif
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace_back.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace_back.pass.cpp
new file mode 100644
index 00000000000000..f2f4a8d22b9057
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace_back.pass.cpp
@@ -0,0 +1,175 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03 && !stdlib=libc++
+
+// <vector>
+
+// template <class... Args> reference emplace_back(Args&&... args);
+// return type is 'reference' in C++17; 'void' before
+
+#include <vector>
+#include <cassert>
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+#include "test_allocator.h"
+
+class A {
+ int i_;
+ double d_;
+
+public:
+ A(const A&) = delete;
+ A& operator=(const A&) = delete;
+
+ TEST_CONSTEXPR_CXX14 A(int i, double d) : i_(i), d_(d) {}
+
+ TEST_CONSTEXPR_CXX14 A(A&& a) : i_(a.i_), d_(a.d_) {
+ a.i_ = 0;
+ a.d_ = 0;
+ }
+
+ TEST_CONSTEXPR_CXX14 A& operator=(A&& a) {
+ i_ = a.i_;
+ d_ = a.d_;
+ a.i_ = 0;
+ a.d_ = 0;
+ return *this;
+ }
+
+ TEST_CONSTEXPR_CXX14 int geti() const { return i_; }
+ TEST_CONSTEXPR_CXX14 double getd() const { return d_; }
+};
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+ {
+ std::vector<A> c;
+#if TEST_STD_VER > 14
+ A& r1 = c.emplace_back(2, 3.5);
+ assert(c.size() == 1);
+ assert(&r1 == &c.back());
+ assert(c.front().geti() == 2);
+ assert(c.front().getd() == 3.5);
+ A& r2 = c.emplace_back(3, 4.5);
+ assert(c.size() == 2);
+ assert(&r2 == &c.back());
+#else
+ c.emplace_back(2, 3.5);
+ assert(c.size() == 1);
+ assert(c.front().geti() == 2);
+ assert(c.front().getd() == 3.5);
+ c.emplace_back(3, 4.5);
+ assert(c.size() == 2);
+#endif
+ assert(c.front().geti() == 2);
+ assert(c.front().getd() == 3.5);
+ assert(c.back().geti() == 3);
+ assert(c.back().getd() == 4.5);
+ }
+ {
+ std::vector<A, limited_allocator<A, 4> > c;
+#if TEST_STD_VER > 14
+ A& r1 = c.emplace_back(2, 3.5);
+ assert(c.size() == 1);
+ assert(&r1 == &c.back());
+ assert(c.front().geti() == 2);
+ assert(c.front().getd() == 3.5);
+ A& r2 = c.emplace_back(3, 4.5);
+ assert(c.size() == 2);
+ assert(&r2 == &c.back());
+#else
+ c.emplace_back(2, 3.5);
+ assert(c.size() == 1);
+ assert(c.front().geti() == 2);
+ assert(c.front().getd() == 3.5);
+ c.emplace_back(3, 4.5);
+ assert(c.size() == 2);
+#endif
+ assert(c.front().geti() == 2);
+ assert(c.front().getd() == 3.5);
+ assert(c.back().geti() == 3);
+ assert(c.back().getd() == 4.5);
+ }
+ {
+ std::vector<A, min_allocator<A> > c;
+#if TEST_STD_VER > 14
+ A& r1 = c.emplace_back(2, 3.5);
+ assert(c.size() == 1);
+ assert(&r1 == &c.back());
+ assert(c.front().geti() == 2);
+ assert(c.front().getd() == 3.5);
+ A& r2 = c.emplace_back(3, 4.5);
+ assert(c.size() == 2);
+ assert(&r2 == &c.back());
+#else
+ c.emplace_back(2, 3.5);
+ assert(c.size() == 1);
+ assert(c.front().geti() == 2);
+ assert(c.front().getd() == 3.5);
+ c.emplace_back(3, 4.5);
+ assert(c.size() == 2);
+#endif
+ assert(c.front().geti() == 2);
+ assert(c.front().getd() == 3.5);
+ assert(c.back().geti() == 3);
+ assert(c.back().getd() == 4.5);
+ }
+ {
+ std::vector<A, safe_allocator<A> > c;
+#if TEST_STD_VER > 14
+ A& r1 = c.emplace_back(2, 3.5);
+ assert(c.size() == 1);
+ assert(&r1 == &c.back());
+ assert(c.front().geti() == 2);
+ assert(c.front().getd() == 3.5);
+ A& r2 = c.emplace_back(3, 4.5);
+ assert(c.size() == 2);
+ assert(&r2 == &c.back());
+#else
+ c.emplace_back(2, 3.5);
+ assert(c.size() == 1);
+ assert(c.front().geti() == 2);
+ assert(c.front().getd() == 3.5);
+ c.emplace_back(3, 4.5);
+ assert(c.size() == 2);
+#endif
+ assert(c.front().geti() == 2);
+ assert(c.front().getd() == 3.5);
+ assert(c.back().geti() == 3);
+ assert(c.back().getd() == 4.5);
+ }
+ {
+ std::vector<Tag_X, TaggingAllocator<Tag_X> > c;
+ c.emplace_back();
+ assert(c.size() == 1);
+ c.emplace_back(1, 2, 3);
+ assert(c.size() == 2);
+ }
+
+ { // LWG 2164
+ int arr[] = {0, 1, 2, 3, 4};
+ int sz = 5;
+ std::vector<int> c(arr, arr + sz);
+ while (c.size() < c.capacity())
+ c.push_back(sz++);
+ c.emplace_back(c.front());
+ assert(c.back() == 0);
+ for (int i = 0; i < sz; ++i)
+ assert(c[i] == i);
+ }
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+#if TEST_STD_VER > 17
+ static_assert(tests());
+#endif
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace_extra.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace_extra.pass.cpp
new file mode 100644
index 00000000000000..0ec7155cb4e5b4
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace_extra.pass.cpp
@@ -0,0 +1,88 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03
+
+// <vector>
+
+// template <class... Args> iterator emplace(const_iterator pos, Args&&... args);
+
+#include <vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "min_allocator.h"
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+ {
+ std::vector<int> v;
+ v.reserve(3);
+ v = {1, 2, 3};
+ v.emplace(v.begin(), v.back());
+ assert(v[0] == 3);
+ }
+ {
+ std::vector<int> v;
+ v.reserve(4);
+ v = {1, 2, 3};
+ v.emplace(v.begin(), v.back());
+ assert(v[0] == 3);
+ }
+ {
+ std::vector<int, min_allocator<int>> v;
+ v.reserve(3);
+ v = {1, 2, 3};
+ v.emplace(v.begin(), v.back());
+ assert(v[0] == 3);
+ }
+ {
+ std::vector<int, min_allocator<int>> v;
+ v.reserve(4);
+ v = {1, 2, 3};
+ v.emplace(v.begin(), v.back());
+ assert(v[0] == 3);
+ }
+ {
+ std::vector<int, safe_allocator<int>> v;
+ v.reserve(3);
+ v = {1, 2, 3};
+ v.emplace(v.begin(), v.back());
+ assert(v[0] == 3);
+ }
+ {
+ std::vector<int, safe_allocator<int>> v;
+ v.reserve(4);
+ v = {1, 2, 3};
+ v.emplace(v.begin(), v.back());
+ assert(v[0] == 3);
+ }
+ {
+ std::vector<int> v;
+ v.reserve(8);
+ std::size_t old_capacity = v.capacity();
+ assert(old_capacity >= 8);
+
+ v.resize(4); // keep the existing capacity
+ assert(v.capacity() == old_capacity);
+
+ v.emplace(v.cend(), 42);
+ assert(v.size() == 5);
+ assert(v.capacity() == old_capacity);
+ assert(v[4] == 42);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+#if TEST_STD_VER > 17
+ static_assert(tests());
+#endif
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter.addressof.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter.addressof.compile.pass.cpp
new file mode 100644
index 00000000000000..0fce3498fec7e8
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter.addressof.compile.pass.cpp
@@ -0,0 +1,23 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// iterator erase(const_iterator position);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <vector>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+ std::vector<operator_hijacker> v;
+ v.erase(v.end());
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter.pass.cpp
new file mode 100644
index 00000000000000..afaecc7ad59cb4
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter.pass.cpp
@@ -0,0 +1,156 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// iterator erase(const_iterator position);
+
+#include <vector>
+#include <iterator>
+#include <cassert>
+
+#include "min_allocator.h"
+#include "MoveOnly.h"
+#include "test_macros.h"
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+struct Throws {
+ Throws() : v_(0) {}
+ Throws(int v) : v_(v) {}
+ Throws(const Throws& rhs) : v_(rhs.v_) {
+ if (sThrows)
+ throw 1;
+ }
+ Throws(Throws&& rhs) : v_(rhs.v_) {
+ if (sThrows)
+ throw 1;
+ }
+ Throws& operator=(const Throws& rhs) {
+ v_ = rhs.v_;
+ return *this;
+ }
+ Throws& operator=(Throws&& rhs) {
+ v_ = rhs.v_;
+ return *this;
+ }
+ int v_;
+ static bool sThrows;
+};
+
+bool Throws::sThrows = false;
+#endif
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+ {
+ int a1[] = {1, 2, 3, 4, 5};
+ std::vector<int> l1(a1, a1 + 5);
+ l1.erase(l1.begin());
+ assert(l1 == std::vector<int>(a1 + 1, a1 + 5));
+ }
+ {
+ int a1[] = {1, 2, 3, 4, 5};
+ int e1[] = {1, 3, 4, 5};
+ std::vector<int> l1(a1, a1 + 5);
+ l1.erase(l1.begin() + 1);
+ assert(l1 == std::vector<int>(e1, e1 + 4));
+ }
+ {
+ int a1[] = {1, 2, 3};
+ std::vector<int> l1(a1, a1 + 3);
+ std::vector<int>::const_iterator i = l1.begin();
+ ++i;
+ std::vector<int>::iterator j = l1.erase(i);
+ assert(l1.size() == 2);
+ assert(std::distance(l1.begin(), l1.end()) == 2);
+ assert(*j == 3);
+ assert(*l1.begin() == 1);
+ assert(*std::next(l1.begin()) == 3);
+ j = l1.erase(j);
+ assert(j == l1.end());
+ assert(l1.size() == 1);
+ assert(std::distance(l1.begin(), l1.end()) == 1);
+ assert(*l1.begin() == 1);
+ j = l1.erase(l1.begin());
+ assert(j == l1.end());
+ assert(l1.size() == 0);
+ assert(std::distance(l1.begin(), l1.end()) == 0);
+ }
+
+ // Make sure vector::erase works with move-only types
+ // When non-trivial
+ {
+ std::vector<MoveOnly> v;
+ v.emplace_back(1);
+ v.emplace_back(2);
+ v.emplace_back(3);
+ v.erase(v.begin());
+ assert(v.size() == 2);
+ assert(v[0] == MoveOnly(2));
+ assert(v[1] == MoveOnly(3));
+ }
+ // When trivial
+ {
+ std::vector<TrivialMoveOnly> v;
+ v.emplace_back(1);
+ v.emplace_back(2);
+ v.emplace_back(3);
+ v.erase(v.begin());
+ assert(v.size() == 2);
+ assert(v[0] == TrivialMoveOnly(2));
+ assert(v[1] == TrivialMoveOnly(3));
+ }
+
+#if TEST_STD_VER >= 11
+ {
+ int a1[] = {1, 2, 3};
+ std::vector<int, min_allocator<int>> l1(a1, a1 + 3);
+ std::vector<int, min_allocator<int>>::const_iterator i = l1.begin();
+ ++i;
+ std::vector<int, min_allocator<int>>::iterator j = l1.erase(i);
+ assert(l1.size() == 2);
+ assert(std::distance(l1.begin(), l1.end()) == 2);
+ assert(*j == 3);
+ assert(*l1.begin() == 1);
+ assert(*std::next(l1.begin()) == 3);
+ j = l1.erase(j);
+ assert(j == l1.end());
+ assert(l1.size() == 1);
+ assert(std::distance(l1.begin(), l1.end()) == 1);
+ assert(*l1.begin() == 1);
+ j = l1.erase(l1.begin());
+ assert(j == l1.end());
+ assert(l1.size() == 0);
+ assert(std::distance(l1.begin(), l1.end()) == 0);
+ }
+#endif
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+#if TEST_STD_VER > 17
+ static_assert(tests());
+#endif
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ // Test for LWG2853:
+ // Throws: Nothing unless an exception is thrown by the assignment operator or move assignment operator of T.
+ {
+ Throws arr[] = {1, 2, 3};
+ std::vector<Throws> v(arr, arr + 3);
+ Throws::sThrows = true;
+ v.erase(v.begin());
+ v.erase(--v.end());
+ v.erase(v.begin());
+ assert(v.size() == 0);
+ }
+#endif
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter_iter.addressof.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter_iter.addressof.compile.pass.cpp
new file mode 100644
index 00000000000000..bc90fa783e98f5
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter_iter.addressof.compile.pass.cpp
@@ -0,0 +1,23 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// iterator erase(const_iterator position);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <vector>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+ std::vector<operator_hijacker> v;
+ v.erase(v.begin(), v.end());
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter_iter.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter_iter.pass.cpp
new file mode 100644
index 00000000000000..80ed572e195624
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter_iter.pass.cpp
@@ -0,0 +1,174 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// iterator erase(const_iterator first, const_iterator last);
+
+#include <vector>
+#include <iterator>
+#include <cassert>
+
+#include "min_allocator.h"
+#include "MoveOnly.h"
+#include "test_macros.h"
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+struct Throws {
+ Throws() : v_(0) {}
+ Throws(int v) : v_(v) {}
+ Throws(const Throws& rhs) : v_(rhs.v_) {
+ if (sThrows)
+ throw 1;
+ }
+ Throws(Throws&& rhs) : v_(rhs.v_) {
+ if (sThrows)
+ throw 1;
+ }
+ Throws& operator=(const Throws& rhs) {
+ v_ = rhs.v_;
+ return *this;
+ }
+ Throws& operator=(Throws&& rhs) {
+ v_ = rhs.v_;
+ return *this;
+ }
+ int v_;
+ static bool sThrows;
+};
+
+bool Throws::sThrows = false;
+#endif
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+ int a1[] = {1, 2, 3};
+ {
+ std::vector<int> l1(a1, a1 + 3);
+ std::vector<int>::iterator i = l1.erase(l1.cbegin(), l1.cbegin());
+ assert(l1.size() == 3);
+ assert(std::distance(l1.cbegin(), l1.cend()) == 3);
+ assert(i == l1.begin());
+ }
+ {
+ std::vector<int> l1(a1, a1 + 3);
+ std::vector<int>::iterator i = l1.erase(l1.cbegin(), std::next(l1.cbegin()));
+ assert(l1.size() == 2);
+ assert(std::distance(l1.cbegin(), l1.cend()) == 2);
+ assert(i == l1.begin());
+ assert(l1 == std::vector<int>(a1 + 1, a1 + 3));
+ }
+ {
+ std::vector<int> l1(a1, a1 + 3);
+ std::vector<int>::iterator i = l1.erase(l1.cbegin(), std::next(l1.cbegin(), 2));
+ assert(l1.size() == 1);
+ assert(std::distance(l1.cbegin(), l1.cend()) == 1);
+ assert(i == l1.begin());
+ assert(l1 == std::vector<int>(a1 + 2, a1 + 3));
+ }
+ {
+ std::vector<int> l1(a1, a1 + 3);
+ std::vector<int>::iterator i = l1.erase(l1.cbegin(), std::next(l1.cbegin(), 3));
+ assert(l1.size() == 0);
+ assert(std::distance(l1.cbegin(), l1.cend()) == 0);
+ assert(i == l1.begin());
+ }
+ {
+ std::vector<std::vector<int> > outer(2, std::vector<int>(1));
+ outer.erase(outer.begin(), outer.begin());
+ assert(outer.size() == 2);
+ assert(outer[0].size() == 1);
+ assert(outer[1].size() == 1);
+ }
+ // Make sure vector::erase works with move-only types
+ { // When non-trivial
+ {
+ std::vector<MoveOnly> v;
+ v.emplace_back(1);
+ v.emplace_back(2);
+ v.emplace_back(3);
+ v.erase(v.begin(), v.begin() + 2);
+ assert(v.size() == 1);
+ assert(v[0] == MoveOnly(3));
+ }
+ // When trivial
+ {
+ std::vector<TrivialMoveOnly> v;
+ v.emplace_back(1);
+ v.emplace_back(2);
+ v.emplace_back(3);
+ v.erase(v.begin(), v.begin() + 2);
+ assert(v.size() == 1);
+ assert(v[0] == TrivialMoveOnly(3));
+ }
+ }
+#if TEST_STD_VER >= 11
+ {
+ std::vector<int, min_allocator<int>> l1(a1, a1 + 3);
+ std::vector<int, min_allocator<int>>::iterator i = l1.erase(l1.cbegin(), l1.cbegin());
+ assert(l1.size() == 3);
+ assert(std::distance(l1.cbegin(), l1.cend()) == 3);
+ assert(i == l1.begin());
+ }
+ {
+ std::vector<int, min_allocator<int>> l1(a1, a1 + 3);
+ std::vector<int, min_allocator<int>>::iterator i = l1.erase(l1.cbegin(), std::next(l1.cbegin()));
+ assert(l1.size() == 2);
+ assert(std::distance(l1.cbegin(), l1.cend()) == 2);
+ assert(i == l1.begin());
+ assert((l1 == std::vector<int, min_allocator<int>>(a1 + 1, a1 + 3)));
+ }
+ {
+ std::vector<int, min_allocator<int>> l1(a1, a1 + 3);
+ std::vector<int, min_allocator<int>>::iterator i = l1.erase(l1.cbegin(), std::next(l1.cbegin(), 2));
+ assert(l1.size() == 1);
+ assert(std::distance(l1.cbegin(), l1.cend()) == 1);
+ assert(i == l1.begin());
+ assert((l1 == std::vector<int, min_allocator<int>>(a1 + 2, a1 + 3)));
+ }
+ {
+ std::vector<int, min_allocator<int>> l1(a1, a1 + 3);
+ std::vector<int, min_allocator<int>>::iterator i = l1.erase(l1.cbegin(), std::next(l1.cbegin(), 3));
+ assert(l1.size() == 0);
+ assert(std::distance(l1.cbegin(), l1.cend()) == 0);
+ assert(i == l1.begin());
+ }
+ {
+ std::vector<std::vector<int, min_allocator<int>>, min_allocator<std::vector<int, min_allocator<int>>>> outer(
+ 2, std::vector<int, min_allocator<int>>(1));
+ outer.erase(outer.begin(), outer.begin());
+ assert(outer.size() == 2);
+ assert(outer[0].size() == 1);
+ assert(outer[1].size() == 1);
+ }
+#endif
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+#if TEST_STD_VER > 17
+ static_assert(tests());
+#endif
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ // Test for LWG2853:
+ // Throws: Nothing unless an exception is thrown by the assignment operator or move assignment operator of T.
+ {
+ Throws arr[] = {1, 2, 3};
+ std::vector<Throws> v(arr, arr + 3);
+ Throws::sThrows = true;
+ v.erase(v.begin(), --v.end());
+ assert(v.size() == 1);
+ v.erase(v.begin(), v.end());
+ assert(v.size() == 0);
+ }
+#endif
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_initializer_list.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_initializer_list.pass.cpp
new file mode 100644
index 00000000000000..c6c77debde5a8e
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_initializer_list.pass.cpp
@@ -0,0 +1,110 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03
+
+// <vector>
+
+// iterator insert(const_iterator p, initializer_list<value_type> il);
+
+#include <vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "min_allocator.h"
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+int throw_if_zero = 2;
+int constructed_count = 0;
+
+struct ThrowSometimes {
+ ThrowSometimes() { ++constructed_count; }
+ ThrowSometimes(const ThrowSometimes&) {
+ if (--throw_if_zero == 0)
+ throw 1;
+ ++constructed_count;
+ }
+ ThrowSometimes& operator=(const ThrowSometimes&) {
+ if (--throw_if_zero == 0)
+ throw 1;
+ ++constructed_count;
+ return *this;
+ }
+ ~ThrowSometimes() { --constructed_count; }
+};
+
+void test_throwing() {
+ std::vector<ThrowSometimes> v;
+ v.reserve(4);
+ v.emplace_back();
+ v.emplace_back();
+ try {
+ v.insert(v.end(), {ThrowSometimes{}, ThrowSometimes{}});
+ assert(false);
+ } catch (int) {
+ assert(v.size() == 2);
+ assert(constructed_count == 2);
+ }
+}
+#endif // TEST_HAS_NO_EXCEPTIONS
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+ {
+ std::vector<int> d(10, 1);
+ std::vector<int>::iterator i = d.insert(d.cbegin() + 2, {3, 4, 5, 6});
+ assert(d.size() == 14);
+ assert(i == d.begin() + 2);
+ assert(d[0] == 1);
+ assert(d[1] == 1);
+ assert(d[2] == 3);
+ assert(d[3] == 4);
+ assert(d[4] == 5);
+ assert(d[5] == 6);
+ assert(d[6] == 1);
+ assert(d[7] == 1);
+ assert(d[8] == 1);
+ assert(d[9] == 1);
+ assert(d[10] == 1);
+ assert(d[11] == 1);
+ assert(d[12] == 1);
+ assert(d[13] == 1);
+ }
+ {
+ std::vector<int, min_allocator<int>> d(10, 1);
+ std::vector<int, min_allocator<int>>::iterator i = d.insert(d.cbegin() + 2, {3, 4, 5, 6});
+ assert(d.size() == 14);
+ assert(i == d.begin() + 2);
+ assert(d[0] == 1);
+ assert(d[1] == 1);
+ assert(d[2] == 3);
+ assert(d[3] == 4);
+ assert(d[4] == 5);
+ assert(d[5] == 6);
+ assert(d[6] == 1);
+ assert(d[7] == 1);
+ assert(d[8] == 1);
+ assert(d[9] == 1);
+ assert(d[10] == 1);
+ assert(d[11] == 1);
+ assert(d[12] == 1);
+ assert(d[13] == 1);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ test_throwing();
+#endif
+ tests();
+#if TEST_STD_VER > 17
+ static_assert(tests());
+#endif
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_iter_iter.addressof.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_iter_iter.addressof.compile.pass.cpp
new file mode 100644
index 00000000000000..f8311090b37e3c
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_iter_iter.addressof.compile.pass.cpp
@@ -0,0 +1,31 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// template <class Iter>
+// iterator insert(const_iterator position, Iter first, Iter last);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <vector>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+#include "test_iterators.h"
+
+void test(cpp17_input_iterator<operator_hijacker*> i) {
+ {
+ std::vector<operator_hijacker> v;
+ v.insert(v.end(), i, i);
+ }
+ {
+ std::vector<operator_hijacker> v;
+ v.insert(v.end(), v.begin(), v.end());
+ }
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_iter_iter.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_iter_iter.pass.cpp
new file mode 100644
index 00000000000000..df41577ac4c75a
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_iter_iter.pass.cpp
@@ -0,0 +1,182 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// template <class Iter>
+// iterator insert(const_iterator position, Iter first, Iter last);
+
+#include <vector>
+#include <cassert>
+#include <cstddef>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "test_iterators.h"
+#include "min_allocator.h"
+
+namespace adl {
+struct S {};
+void make_move_iterator(S*) {}
+} // namespace adl
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+ {
+ typedef std::vector<int> V;
+ V v(100);
+ int a[] = {1, 2, 3, 4, 5};
+ const int N = sizeof(a) / sizeof(a[0]);
+ V::iterator i =
+ v.insert(v.cbegin() + 10, cpp17_input_iterator<const int*>(a), cpp17_input_iterator<const int*>(a + N));
+ assert(v.size() == 100 + N);
+ assert(i == v.begin() + 10);
+ int j;
+ for (j = 0; j < 10; ++j)
+ assert(v[j] == 0);
+ for (std::size_t k = 0; k < N; ++j, ++k)
+ assert(v[j] == a[k]);
+ for (; j < 105; ++j)
+ assert(v[j] == 0);
+ }
+ {
+ typedef std::vector<int> V;
+ V v(100);
+ int a[] = {1, 2, 3, 4, 5};
+ const int N = sizeof(a) / sizeof(a[0]);
+ V::iterator i = v.insert(v.cbegin() + 10, forward_iterator<const int*>(a), forward_iterator<const int*>(a + N));
+ assert(v.size() == 100 + N);
+ assert(i == v.begin() + 10);
+ int j;
+ for (j = 0; j < 10; ++j)
+ assert(v[j] == 0);
+ for (std::size_t k = 0; k < N; ++j, ++k)
+ assert(v[j] == a[k]);
+ for (; j < 105; ++j)
+ assert(v[j] == 0);
+ }
+ {
+ typedef std::vector<int> V;
+ V v(100);
+ while (v.size() < v.capacity())
+ v.push_back(0); // force reallocation
+ std::size_t sz = v.size();
+ int a[] = {1, 2, 3, 4, 5};
+ const unsigned N = sizeof(a) / sizeof(a[0]);
+ V::iterator i = v.insert(v.cbegin() + 10, forward_iterator<const int*>(a), forward_iterator<const int*>(a + N));
+ assert(v.size() == sz + N);
+ assert(i == v.begin() + 10);
+ std::size_t j;
+ for (j = 0; j < 10; ++j)
+ assert(v[j] == 0);
+ for (std::size_t k = 0; k < N; ++j, ++k)
+ assert(v[j] == a[k]);
+ for (; j < v.size(); ++j)
+ assert(v[j] == 0);
+ }
+ {
+ typedef std::vector<int> V;
+ V v(100);
+ v.reserve(128); // force no reallocation
+ std::size_t sz = v.size();
+ int a[] = {1, 2, 3, 4, 5};
+ const unsigned N = sizeof(a) / sizeof(a[0]);
+ V::iterator i = v.insert(v.cbegin() + 10, forward_iterator<const int*>(a), forward_iterator<const int*>(a + N));
+ assert(v.size() == sz + N);
+ assert(i == v.begin() + 10);
+ std::size_t j;
+ for (j = 0; j < 10; ++j)
+ assert(v[j] == 0);
+ for (std::size_t k = 0; k < N; ++j, ++k)
+ assert(v[j] == a[k]);
+ for (; j < v.size(); ++j)
+ assert(v[j] == 0);
+ }
+ {
+ typedef std::vector<int, limited_allocator<int, 308> > V;
+ V v(100);
+ int a[] = {1, 2, 3, 4, 5};
+ const int N = sizeof(a) / sizeof(a[0]);
+ V::iterator i =
+ v.insert(v.cbegin() + 10, cpp17_input_iterator<const int*>(a), cpp17_input_iterator<const int*>(a + N));
+ assert(v.size() == 100 + N);
+ assert(i == v.begin() + 10);
+ int j;
+ for (j = 0; j < 10; ++j)
+ assert(v[j] == 0);
+ for (std::size_t k = 0; k < N; ++j, ++k)
+ assert(v[j] == a[k]);
+ for (; j < 105; ++j)
+ assert(v[j] == 0);
+ }
+ {
+ typedef std::vector<int, limited_allocator<int, 300> > V;
+ V v(100);
+ int a[] = {1, 2, 3, 4, 5};
+ const int N = sizeof(a) / sizeof(a[0]);
+ V::iterator i = v.insert(v.cbegin() + 10, forward_iterator<const int*>(a), forward_iterator<const int*>(a + N));
+ assert(v.size() == 100 + N);
+ assert(i == v.begin() + 10);
+ int j;
+ for (j = 0; j < 10; ++j)
+ assert(v[j] == 0);
+ for (std::size_t k = 0; k < N; ++j, ++k)
+ assert(v[j] == a[k]);
+ for (; j < 105; ++j)
+ assert(v[j] == 0);
+ }
+#if TEST_STD_VER >= 11
+ {
+ typedef std::vector<int, min_allocator<int> > V;
+ V v(100);
+ int a[] = {1, 2, 3, 4, 5};
+ const int N = sizeof(a) / sizeof(a[0]);
+ V::iterator i =
+ v.insert(v.cbegin() + 10, cpp17_input_iterator<const int*>(a), cpp17_input_iterator<const int*>(a + N));
+ assert(v.size() == 100 + N);
+ assert(i == v.begin() + 10);
+ int j;
+ for (j = 0; j < 10; ++j)
+ assert(v[j] == 0);
+ for (std::size_t k = 0; k < N; ++j, ++k)
+ assert(v[j] == a[k]);
+ for (; j < 105; ++j)
+ assert(v[j] == 0);
+ }
+ {
+ typedef std::vector<int, min_allocator<int> > V;
+ V v(100);
+ int a[] = {1, 2, 3, 4, 5};
+ const int N = sizeof(a) / sizeof(a[0]);
+ V::iterator i = v.insert(v.cbegin() + 10, forward_iterator<const int*>(a), forward_iterator<const int*>(a + N));
+ assert(v.size() == 100 + N);
+ assert(i == v.begin() + 10);
+ int j;
+ for (j = 0; j < 10; ++j)
+ assert(v[j] == 0);
+ for (std::size_t k = 0; k < N; ++j, ++k)
+ assert(v[j] == a[k]);
+ for (; j < 105; ++j)
+ assert(v[j] == 0);
+ }
+#endif
+
+ {
+ std::vector<adl::S> s;
+ s.insert(s.end(), cpp17_input_iterator<adl::S*>(nullptr), cpp17_input_iterator<adl::S*>(nullptr));
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+#if TEST_STD_VER > 17
+ static_assert(tests());
+#endif
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_lvalue.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_lvalue.pass.cpp
new file mode 100644
index 00000000000000..29c4d1709689a7
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_lvalue.pass.cpp
@@ -0,0 +1,137 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// iterator insert(const_iterator position, const value_type& x);
+
+#include <vector>
+#include <cassert>
+#include <cstddef>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+TEST_CONSTEXPR_CXX20 bool test() {
+ {
+ std::vector<int> v(100);
+ const int lvalue = 1;
+ std::vector<int>::iterator i = v.insert(v.cbegin() + 10, lvalue);
+ assert(v.size() == 101);
+ assert(i == v.begin() + 10);
+ int j;
+ for (j = 0; j < 10; ++j)
+ assert(v[j] == 0);
+ assert(v[j] == 1);
+ for (++j; j < 101; ++j)
+ assert(v[j] == 0);
+ }
+ {
+ const std::size_t n = 100;
+ std::vector<int> v(n);
+ v.reserve(n + 1);
+ const int lvalue = 1;
+
+ // no reallocation expected
+ std::vector<int>::iterator it = v.insert(v.cbegin() + n, lvalue);
+
+ assert(v.size() == n + 1);
+ assert(it == v.begin() + n);
+ for (std::size_t i = 0; i < n; ++i) {
+ assert(v[i] == 0);
+ }
+ assert(v[n] == lvalue);
+ }
+ {
+ std::vector<int> v(100);
+ while (v.size() < v.capacity())
+ v.push_back(0); // force reallocation
+ std::size_t sz = v.size();
+ const int lvalue = 1;
+ std::vector<int>::iterator i = v.insert(v.cbegin() + 10, lvalue);
+ assert(v.size() == sz + 1);
+ assert(i == v.begin() + 10);
+ std::size_t j;
+ for (j = 0; j < 10; ++j)
+ assert(v[j] == 0);
+ assert(v[j] == 1);
+ for (++j; j < v.size(); ++j)
+ assert(v[j] == 0);
+ }
+ {
+ std::vector<int> v(100);
+ while (v.size() < v.capacity())
+ v.push_back(0);
+ v.pop_back();
+ v.pop_back(); // force no reallocation
+ std::size_t sz = v.size();
+ const int lvalue = 1;
+ std::vector<int>::iterator i = v.insert(v.cbegin() + 10, lvalue);
+ assert(v.size() == sz + 1);
+ assert(i == v.begin() + 10);
+ std::size_t j;
+ for (j = 0; j < 10; ++j)
+ assert(v[j] == 0);
+ assert(v[j] == 1);
+ for (++j; j < v.size(); ++j)
+ assert(v[j] == 0);
+ }
+ {
+ std::vector<int, limited_allocator<int, 300> > v(100);
+ const int lvalue = 1;
+ std::vector<int, limited_allocator<int, 300> >::iterator i = v.insert(v.cbegin() + 10, lvalue);
+ assert(v.size() == 101);
+ assert(i == v.begin() + 10);
+ int j;
+ for (j = 0; j < 10; ++j)
+ assert(v[j] == 0);
+ assert(v[j] == 1);
+ for (++j; j < 101; ++j)
+ assert(v[j] == 0);
+ }
+#if TEST_STD_VER >= 11
+ {
+ std::vector<int, min_allocator<int>> v(100);
+ const int lvalue = 1;
+ std::vector<int, min_allocator<int>>::iterator i = v.insert(v.cbegin() + 10, lvalue);
+ assert(v.size() == 101);
+ assert(i == v.begin() + 10);
+ int j;
+ for (j = 0; j < 10; ++j)
+ assert(v[j] == 0);
+ assert(v[j] == 1);
+ for (++j; j < 101; ++j)
+ assert(v[j] == 0);
+ }
+ {
+ std::vector<int, safe_allocator<int>> v(100);
+ const int lvalue = 1;
+ std::vector<int, safe_allocator<int>>::iterator i = v.insert(v.cbegin() + 10, lvalue);
+ assert(v.size() == 101);
+ assert(i == v.begin() + 10);
+ int j;
+ for (j = 0; j < 10; ++j)
+ assert(v[j] == 0);
+ assert(v[j] == 1);
+ for (++j; j < 101; ++j)
+ assert(v[j] == 0);
+ }
+#endif
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+#if TEST_STD_VER > 17
+ static_assert(test());
+#endif
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_rvalue.addressof.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_rvalue.addressof.compile.pass.cpp
new file mode 100644
index 00000000000000..11f24604eeac4d
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_rvalue.addressof.compile.pass.cpp
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03 && !stdlib=libc++
+
+// <vector>
+
+// iterator insert(const_iterator position, value_type&& x);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <vector>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+ std::vector<operator_hijacker> v;
+ v.insert(v.end(), operator_hijacker());
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_rvalue.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_rvalue.pass.cpp
new file mode 100644
index 00000000000000..e72bba1ca3551e
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_rvalue.pass.cpp
@@ -0,0 +1,82 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03 && !stdlib=libc++
+
+// <vector>
+
+// iterator insert(const_iterator position, value_type&& x);
+
+#include <vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "MoveOnly.h"
+#include "min_allocator.h"
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+ {
+ std::vector<MoveOnly> v(100);
+ std::vector<MoveOnly>::iterator i = v.insert(v.cbegin() + 10, MoveOnly(3));
+ assert(v.size() == 101);
+ assert(i == v.begin() + 10);
+ int j;
+ for (j = 0; j < 10; ++j)
+ assert(v[j] == MoveOnly());
+ assert(v[j] == MoveOnly(3));
+ for (++j; j < 101; ++j)
+ assert(v[j] == MoveOnly());
+ }
+ {
+ std::vector<MoveOnly, limited_allocator<MoveOnly, 300> > v(100);
+ std::vector<MoveOnly, limited_allocator<MoveOnly, 300> >::iterator i = v.insert(v.cbegin() + 10, MoveOnly(3));
+ assert(v.size() == 101);
+ assert(i == v.begin() + 10);
+ int j;
+ for (j = 0; j < 10; ++j)
+ assert(v[j] == MoveOnly());
+ assert(v[j] == MoveOnly(3));
+ for (++j; j < 101; ++j)
+ assert(v[j] == MoveOnly());
+ }
+ {
+ std::vector<MoveOnly, min_allocator<MoveOnly> > v(100);
+ std::vector<MoveOnly, min_allocator<MoveOnly> >::iterator i = v.insert(v.cbegin() + 10, MoveOnly(3));
+ assert(v.size() == 101);
+ assert(i == v.begin() + 10);
+ int j;
+ for (j = 0; j < 10; ++j)
+ assert(v[j] == MoveOnly());
+ assert(v[j] == MoveOnly(3));
+ for (++j; j < 101; ++j)
+ assert(v[j] == MoveOnly());
+ }
+ {
+ std::vector<MoveOnly, safe_allocator<MoveOnly> > v(100);
+ std::vector<MoveOnly, safe_allocator<MoveOnly> >::iterator i = v.insert(v.cbegin() + 10, MoveOnly(3));
+ assert(v.size() == 101);
+ assert(i == v.begin() + 10);
+ int j;
+ for (j = 0; j < 10; ++j)
+ assert(v[j] == MoveOnly());
+ assert(v[j] == MoveOnly(3));
+ for (++j; j < 101; ++j)
+ assert(v[j] == MoveOnly());
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+#if TEST_STD_VER > 17
+ static_assert(tests());
+#endif
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_size_value.addressof.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_size_value.addressof.compile.pass.cpp
new file mode 100644
index 00000000000000..c02b92a4998e85
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_size_value.addressof.compile.pass.cpp
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// iterator insert(const_iterator position, size_type n, const value_type& x);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <vector>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+ std::vector<operator_hijacker> v;
+ operator_hijacker val;
+ v.insert(v.end(), 1, val);
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_size_value.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_size_value.pass.cpp
new file mode 100644
index 00000000000000..940f4602d128af
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_size_value.pass.cpp
@@ -0,0 +1,117 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// iterator insert(const_iterator position, size_type n, const value_type& x);
+
+#include <vector>
+#include <cassert>
+#include <cstddef>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+ {
+ std::vector<int> v(100);
+ std::vector<int>::iterator i = v.insert(v.cbegin() + 10, 5, 1);
+ assert(v.size() == 105);
+ assert(i == v.begin() + 10);
+ int j;
+ for (j = 0; j < 10; ++j)
+ assert(v[j] == 0);
+ for (; j < 15; ++j)
+ assert(v[j] == 1);
+ for (++j; j < 105; ++j)
+ assert(v[j] == 0);
+ }
+ {
+ std::vector<int> v(100);
+ while (v.size() < v.capacity())
+ v.push_back(0); // force reallocation
+ std::size_t sz = v.size();
+ std::vector<int>::iterator i = v.insert(v.cbegin() + 10, 5, 1);
+ assert(v.size() == sz + 5);
+ assert(i == v.begin() + 10);
+ std::size_t j;
+ for (j = 0; j < 10; ++j)
+ assert(v[j] == 0);
+ for (; j < 15; ++j)
+ assert(v[j] == 1);
+ for (++j; j < v.size(); ++j)
+ assert(v[j] == 0);
+ }
+ {
+ std::vector<int> v(100);
+ v.reserve(128); // force no reallocation
+ std::size_t sz = v.size();
+ std::vector<int>::iterator i = v.insert(v.cbegin() + 10, 5, 1);
+ assert(v.size() == sz + 5);
+ assert(i == v.begin() + 10);
+ std::size_t j;
+ for (j = 0; j < 10; ++j)
+ assert(v[j] == 0);
+ for (; j < 15; ++j)
+ assert(v[j] == 1);
+ for (++j; j < v.size(); ++j)
+ assert(v[j] == 0);
+ }
+ {
+ std::vector<int, limited_allocator<int, 300> > v(100);
+ std::vector<int, limited_allocator<int, 300> >::iterator i = v.insert(v.cbegin() + 10, 5, 1);
+ assert(v.size() == 105);
+ assert(i == v.begin() + 10);
+ int j;
+ for (j = 0; j < 10; ++j)
+ assert(v[j] == 0);
+ for (; j < 15; ++j)
+ assert(v[j] == 1);
+ for (++j; j < 105; ++j)
+ assert(v[j] == 0);
+ }
+#if TEST_STD_VER >= 11
+ {
+ std::vector<int, min_allocator<int>> v(100);
+ std::vector<int, min_allocator<int>>::iterator i = v.insert(v.cbegin() + 10, 5, 1);
+ assert(v.size() == 105);
+ assert(i == v.begin() + 10);
+ int j;
+ for (j = 0; j < 10; ++j)
+ assert(v[j] == 0);
+ for (; j < 15; ++j)
+ assert(v[j] == 1);
+ for (++j; j < 105; ++j)
+ assert(v[j] == 0);
+ }
+ {
+ std::vector<int, safe_allocator<int>> v(100);
+ std::vector<int, safe_allocator<int>>::iterator i = v.insert(v.cbegin() + 10, 5, 1);
+ assert(v.size() == 105);
+ assert(i == v.begin() + 10);
+ int j;
+ for (j = 0; j < 10; ++j)
+ assert(v[j] == 0);
+ for (; j < 15; ++j)
+ assert(v[j] == 1);
+ for (++j; j < 105; ++j)
+ assert(v[j] == 0);
+ }
+#endif
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+#if TEST_STD_VER > 17
+ static_assert(tests());
+#endif
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_value.addressof.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_value.addressof.compile.pass.cpp
new file mode 100644
index 00000000000000..fbf1a4f50b974f
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_value.addressof.compile.pass.cpp
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// iterator insert(const_iterator position, const value_type& x);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <vector>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+ std::vector<operator_hijacker> v;
+ operator_hijacker val;
+ v.insert(v.end(), val);
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_range.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_range.pass.cpp
new file mode 100644
index 00000000000000..5353c958973a1e
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_range.pass.cpp
@@ -0,0 +1,67 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=2000000
+
+// template<container-compatible-range<T> R>
+// constexpr iterator insert_range(const_iterator position, R&& rg); // C++23
+
+#include <vector>
+
+#include "../../insert_range_sequence_containers.h"
+#include "test_macros.h"
+
+// Tested cases:
+// - different kinds of insertions (inserting an {empty/one-element/mid-sized/long range} into an
+// {empty/one-element/full} container at the {beginning/middle/end});
+// - inserting move-only elements;
+// - an exception is thrown when copying the elements or when allocating new elements.
+
+constexpr bool test() {
+ for_all_iterators_and_allocators<int, const int*>([]<class Iter, class Sent, class Alloc>() {
+ test_sequence_insert_range<std::vector<int, Alloc>, Iter, Sent>([]([[maybe_unused]] auto&& c) {});
+ });
+ test_sequence_insert_range_move_only<std::vector>();
+
+ { // Vector may or may not need to reallocate because of the insertion -- make sure to test both cases.
+ { // Ensure reallocation happens.
+ int in[] = {-1, -2, -3, -4, -5, -6, -7, -8, -9, -10};
+ std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8};
+ v.shrink_to_fit();
+ assert(v.capacity() < v.size() + std::ranges::size(in));
+
+ v.insert_range(v.end(), in);
+ assert(std::ranges::equal(v, std::array{1, 2, 3, 4, 5, 6, 7, 8, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10}));
+ }
+
+ { // Ensure no reallocation happens.
+ int in[] = {-1, -2, -3, -4, -5, -6, -7, -8, -9, -10};
+ std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8};
+ v.reserve(v.size() + std::ranges::size(in));
+ assert(v.capacity() >= v.size() + std::ranges::size(in));
+
+ v.insert_range(v.end(), in);
+ assert(std::ranges::equal(v, std::array{1, 2, 3, 4, 5, 6, 7, 8, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10}));
+ }
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ static_assert(test_constraints_insert_range<std::vector, int, double>());
+
+ test_insert_range_exception_safety_throwing_copy<std::vector>();
+ test_insert_range_exception_safety_throwing_allocator<std::vector, int>();
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/pop_back.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/pop_back.pass.cpp
new file mode 100644
index 00000000000000..9717666079d803
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/pop_back.pass.cpp
@@ -0,0 +1,59 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// void pop_back();
+
+#include <vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+ {
+ std::vector<int> c;
+ c.push_back(1);
+ assert(c.size() == 1);
+ c.pop_back();
+ assert(c.size() == 0);
+ }
+#if TEST_STD_VER >= 11
+ {
+ std::vector<int, min_allocator<int>> c;
+ c.push_back(1);
+ assert(c.size() == 1);
+ c.pop_back();
+ assert(c.size() == 0);
+ }
+#endif
+
+ { // LWG 526
+ int arr[] = {0, 1, 2, 3, 4};
+ int sz = 5;
+ std::vector<int> c(arr, arr + sz);
+ while (c.size() < c.capacity())
+ c.push_back(sz++);
+ c.push_back(c.front());
+ assert(c.back() == 0);
+ for (int i = 0; i < sz; ++i)
+ assert(c[i] == i);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+#if TEST_STD_VER > 17
+ static_assert(tests());
+#endif
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/push_back.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/push_back.pass.cpp
new file mode 100644
index 00000000000000..5f23368ffd3bc8
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/push_back.pass.cpp
@@ -0,0 +1,105 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// void push_back(const value_type& x);
+
+#include <vector>
+#include <cassert>
+#include <cstddef>
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+ {
+ std::vector<int> c;
+ c.push_back(0);
+ assert(c.size() == 1);
+ for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+ assert(c[j] == j);
+ c.push_back(1);
+ assert(c.size() == 2);
+ for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+ assert(c[j] == j);
+ c.push_back(2);
+ assert(c.size() == 3);
+ for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+ assert(c[j] == j);
+ c.push_back(3);
+ assert(c.size() == 4);
+ for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+ assert(c[j] == j);
+ c.push_back(4);
+ assert(c.size() == 5);
+ for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+ assert(c[j] == j);
+ }
+ {
+ // libc++ needs 15 because it grows by 2x (1 + 2 + 4 + 8).
+ // Use 17 for implementations that dynamically allocate a container proxy
+ // and grow by 1.5x (1 for proxy + 1 + 2 + 3 + 4 + 6).
+ std::vector<int, limited_allocator<int, 17> > c;
+ c.push_back(0);
+ assert(c.size() == 1);
+ for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+ assert(c[j] == j);
+ c.push_back(1);
+ assert(c.size() == 2);
+ for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+ assert(c[j] == j);
+ c.push_back(2);
+ assert(c.size() == 3);
+ for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+ assert(c[j] == j);
+ c.push_back(3);
+ assert(c.size() == 4);
+ for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+ assert(c[j] == j);
+ c.push_back(4);
+ assert(c.size() == 5);
+ for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+ assert(c[j] == j);
+ }
+#if TEST_STD_VER >= 11
+ {
+ std::vector<int, min_allocator<int>> c;
+ c.push_back(0);
+ assert(c.size() == 1);
+ for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+ assert(c[j] == j);
+ c.push_back(1);
+ assert(c.size() == 2);
+ for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+ assert(c[j] == j);
+ c.push_back(2);
+ assert(c.size() == 3);
+ for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+ assert(c[j] == j);
+ c.push_back(3);
+ assert(c.size() == 4);
+ for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+ assert(c[j] == j);
+ c.push_back(4);
+ assert(c.size() == 5);
+ for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+ assert(c[j] == j);
+ }
+#endif
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+#if TEST_STD_VER > 17
+ static_assert(tests());
+#endif
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/push_back_exception_safety.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/push_back_exception_safety.pass.cpp
new file mode 100644
index 00000000000000..e2cbed783e2c74
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/push_back_exception_safety.pass.cpp
@@ -0,0 +1,88 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// void push_back(const value_type& x);
+
+#include <vector>
+#include <cassert>
+
+#include "test_macros.h"
+
+// Flag that makes the copy constructor for CMyClass throw an exception
+static bool gCopyConstructorShouldThrow = false;
+
+class CMyClass {
+public:
+ CMyClass(int tag);
+
+public:
+ CMyClass(const CMyClass& iOther);
+
+public:
+ ~CMyClass();
+
+ bool equal(const CMyClass& rhs) const { return fTag == rhs.fTag && fMagicValue == rhs.fMagicValue; }
+
+private:
+ int fMagicValue;
+ int fTag;
+
+private:
+ static int kStartedConstructionMagicValue;
+
+private:
+ static int kFinishedConstructionMagicValue;
+};
+
+// Value for fMagicValue when the constructor has started running, but not yet finished
+int CMyClass::kStartedConstructionMagicValue = 0;
+// Value for fMagicValue when the constructor has finished running
+int CMyClass::kFinishedConstructionMagicValue = 12345;
+
+CMyClass::CMyClass(int tag) : fMagicValue(kStartedConstructionMagicValue), fTag(tag) {
+ // Signal that the constructor has finished running
+ fMagicValue = kFinishedConstructionMagicValue;
+}
+
+CMyClass::CMyClass(const CMyClass& iOther) : fMagicValue(kStartedConstructionMagicValue), fTag(iOther.fTag) {
+ // If requested, throw an exception _before_ setting fMagicValue to kFinishedConstructionMagicValue
+ if (gCopyConstructorShouldThrow) {
+ TEST_THROW(std::exception());
+ }
+ // Signal that the constructor has finished running
+ fMagicValue = kFinishedConstructionMagicValue;
+}
+
+CMyClass::~CMyClass() {
+ // Only instances for which the constructor has finished running should be destructed
+ assert(fMagicValue == kFinishedConstructionMagicValue);
+}
+
+bool operator==(const CMyClass& lhs, const CMyClass& rhs) { return lhs.equal(rhs); }
+
+int main(int, char**) {
+ CMyClass instance(42);
+ std::vector<CMyClass> vec;
+
+ vec.push_back(instance);
+ std::vector<CMyClass> vec2(vec);
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ gCopyConstructorShouldThrow = true;
+ try {
+ vec.push_back(instance);
+ assert(false);
+ } catch (...) {
+ assert(vec == vec2);
+ }
+#endif
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/push_back_rvalue.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/push_back_rvalue.pass.cpp
new file mode 100644
index 00000000000000..7f3a33c3d865a3
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/push_back_rvalue.pass.cpp
@@ -0,0 +1,106 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03 && !stdlib=libc++
+
+// <vector>
+
+// void push_back(value_type&& x);
+
+#include <vector>
+#include <cassert>
+#include <cstddef>
+#include "test_macros.h"
+#include "MoveOnly.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+ {
+ std::vector<MoveOnly> c;
+ c.push_back(MoveOnly(0));
+ assert(c.size() == 1);
+ for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+ assert(c[j] == MoveOnly(j));
+ c.push_back(MoveOnly(1));
+ assert(c.size() == 2);
+ for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+ assert(c[j] == MoveOnly(j));
+ c.push_back(MoveOnly(2));
+ assert(c.size() == 3);
+ for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+ assert(c[j] == MoveOnly(j));
+ c.push_back(MoveOnly(3));
+ assert(c.size() == 4);
+ for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+ assert(c[j] == MoveOnly(j));
+ c.push_back(MoveOnly(4));
+ assert(c.size() == 5);
+ for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+ assert(c[j] == MoveOnly(j));
+ }
+ {
+ // libc++ needs 15 because it grows by 2x (1 + 2 + 4 + 8).
+ // Use 17 for implementations that dynamically allocate a container proxy
+ // and grow by 1.5x (1 for proxy + 1 + 2 + 3 + 4 + 6).
+ std::vector<MoveOnly, limited_allocator<MoveOnly, 17> > c;
+ c.push_back(MoveOnly(0));
+ assert(c.size() == 1);
+ for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+ assert(c[j] == MoveOnly(j));
+ c.push_back(MoveOnly(1));
+ assert(c.size() == 2);
+ for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+ assert(c[j] == MoveOnly(j));
+ c.push_back(MoveOnly(2));
+ assert(c.size() == 3);
+ for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+ assert(c[j] == MoveOnly(j));
+ c.push_back(MoveOnly(3));
+ assert(c.size() == 4);
+ for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+ assert(c[j] == MoveOnly(j));
+ c.push_back(MoveOnly(4));
+ assert(c.size() == 5);
+ for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+ assert(c[j] == MoveOnly(j));
+ }
+ {
+ std::vector<MoveOnly, min_allocator<MoveOnly> > c;
+ c.push_back(MoveOnly(0));
+ assert(c.size() == 1);
+ for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+ assert(c[j] == MoveOnly(j));
+ c.push_back(MoveOnly(1));
+ assert(c.size() == 2);
+ for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+ assert(c[j] == MoveOnly(j));
+ c.push_back(MoveOnly(2));
+ assert(c.size() == 3);
+ for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+ assert(c[j] == MoveOnly(j));
+ c.push_back(MoveOnly(3));
+ assert(c.size() == 4);
+ for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+ assert(c[j] == MoveOnly(j));
+ c.push_back(MoveOnly(4));
+ assert(c.size() == 5);
+ for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+ assert(c[j] == MoveOnly(j));
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+#if TEST_STD_VER > 17
+ static_assert(tests());
+#endif
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/resize_not_move_insertable.verify.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/resize_not_move_insertable.verify.cpp
new file mode 100644
index 00000000000000..acc0127ac73e2c
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/resize_not_move_insertable.verify.cpp
@@ -0,0 +1,47 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03 && !stdlib=libc++
+
+// <vector>
+
+// Test that vector produces a decent diagnostic for user types that explicitly
+// delete their move constructor. Such types don't meet the Cpp17CopyInsertable
+// requirements.
+
+#include <vector>
+
+template <int>
+class BadUserNoCookie {
+public:
+ BadUserNoCookie() {}
+
+ BadUserNoCookie(BadUserNoCookie&&) = delete;
+ BadUserNoCookie& operator=(BadUserNoCookie&&) = delete;
+
+ BadUserNoCookie(const BadUserNoCookie&) = default;
+ BadUserNoCookie& operator=(const BadUserNoCookie&) = default;
+};
+
+int main(int, char**) {
+ // expected-error@* 2 {{The specified type does not meet the requirements of Cpp17MoveInsertable}}
+
+ // Other diagnostics that might be seen as Clang tries to continue compiling:
+ // expected-error@* 0-2 {{call to deleted constructor}}
+ // expected-error@* 0-2 {{no matching function for call to '__construct_at'}}
+ {
+ std::vector<BadUserNoCookie<1> > x;
+ x.emplace_back();
+ }
+ {
+ std::vector<BadUserNoCookie<2> > x;
+ BadUserNoCookie<2> c;
+ x.push_back(c);
+ }
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/swap.addressof.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/swap.addressof.compile.pass.cpp
new file mode 100644
index 00000000000000..87330978ef22c9
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/swap.addressof.compile.pass.cpp
@@ -0,0 +1,33 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// template <class T, size_t N>
+// friend void swap(inplace_vector<T, N>& x, inplace_vector<T, N>& y);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <inplace_vector>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+ {
+ std::inplace_vector<operator_hijacker, 0> vo;
+ std::inplace_vector<operator_hijacker, 0> v;
+ v.swap(vo);
+ }
+ {
+ std::inplace_vector<operator_hijacker, 10> vo;
+ std::inplace_vector<operator_hijacker, 10> v;
+ v.swap(vo);
+ }
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/swap.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/swap.pass.cpp
new file mode 100644
index 00000000000000..8a45c7c9eb49d7
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/swap.pass.cpp
@@ -0,0 +1,59 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// void swap(vector& x);
+
+#include <vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "min_allocator.h"
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+ {
+ std::vector<int> v1(100);
+ std::vector<int> v2(200);
+ v1.swap(v2);
+ assert(v1.size() == 200);
+ assert(v1.capacity() == 200);
+ assert(v2.size() == 100);
+ assert(v2.capacity() == 100);
+ }
+#if TEST_STD_VER >= 11
+ {
+ std::vector<int, min_allocator<int>> v1(100);
+ std::vector<int, min_allocator<int>> v2(200);
+ v1.swap(v2);
+ assert(v1.size() == 200);
+ assert(v1.capacity() == 200);
+ assert(v2.size() == 100);
+ assert(v2.capacity() == 100);
+ }
+ {
+ std::vector<int, safe_allocator<int>> v1(100);
+ std::vector<int, safe_allocator<int>> v2(200);
+ v1.swap(v2);
+ assert(v1.size() == 200);
+ assert(v1.capacity() == 200);
+ assert(v2.size() == 100);
+ assert(v2.capacity() == 100);
+ }
+#endif
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+#if TEST_STD_VER > 17
+ static_assert(tests());
+#endif
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/swap_noexcept.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/swap_noexcept.compile.pass.cpp
new file mode 100644
index 00000000000000..48e083e42b15ff
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/swap_noexcept.compile.pass.cpp
@@ -0,0 +1,87 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03
+
+// <vector>
+
+// void swap(vector& c)
+// noexcept(!allocator_type::propagate_on_container_swap::value ||
+// __is_nothrow_swappable<allocator_type>::value);
+//
+// In C++17, the standard says that swap shall have:
+// noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value ||
+// allocator_traits<Allocator>::is_always_equal::value);
+
+// This tests a conforming extension
+
+#include <vector>
+#include <utility>
+#include <cassert>
+
+#include "test_macros.h"
+#include "MoveOnly.h"
+#include "test_allocator.h"
+
+template <class T>
+struct some_alloc {
+ typedef T value_type;
+
+ some_alloc() {}
+ some_alloc(const some_alloc&);
+ void allocate(std::size_t);
+ void deallocate(void*, unsigned) {}
+
+ typedef std::true_type propagate_on_container_swap;
+};
+
+template <class T>
+struct some_alloc2 {
+ typedef T value_type;
+
+ some_alloc2() {}
+ some_alloc2(const some_alloc2&);
+ void allocate(std::size_t);
+ void deallocate(void*, unsigned) {}
+
+ typedef std::false_type propagate_on_container_swap;
+ typedef std::true_type is_always_equal;
+};
+
+void test() {
+ {
+ typedef std::vector<MoveOnly> C;
+ static_assert(noexcept(swap(std::declval<C&>(), std::declval<C&>())), "");
+ }
+#if defined(_LIBCPP_VERSION)
+ {
+ typedef std::vector<MoveOnly, test_allocator<MoveOnly>> C;
+ static_assert(noexcept(swap(std::declval<C&>(), std::declval<C&>())), "");
+ }
+#endif
+ {
+ typedef std::vector<MoveOnly, other_allocator<MoveOnly>> C;
+ static_assert(noexcept(swap(std::declval<C&>(), std::declval<C&>())), "");
+ }
+ {
+ typedef std::vector<MoveOnly, some_alloc<MoveOnly>> C;
+#if TEST_STD_VER >= 14
+ // In C++14, if POCS is set, swapping the allocator is required not to throw
+ static_assert(noexcept(swap(std::declval<C&>(), std::declval<C&>())), "");
+#else
+ static_assert(!noexcept(swap(std::declval<C&>(), std::declval<C&>())), "");
+#endif
+ }
+#if TEST_STD_VER >= 14
+ {
+ typedef std::vector<MoveOnly, some_alloc2<MoveOnly>> C;
+ // If the allocators are always equal, then the swap can be noexcept
+ static_assert(noexcept(swap(std::declval<C&>(), std::declval<C&>())), "");
+ }
+#endif
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.special/swap.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.special/swap.pass.cpp
new file mode 100644
index 00000000000000..51f773ba4f6c5b
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.special/swap.pass.cpp
@@ -0,0 +1,155 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// template <class T, class Alloc>
+// void swap(vector<T,Alloc>& x, vector<T,Alloc>& y);
+
+#include <vector>
+#include <iterator>
+#include <cassert>
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+template <typename A>
+TEST_CONSTEXPR_CXX20 void test_with_allocator() {
+ {
+ int a1[] = {1, 3, 7, 9, 10};
+ int a2[] = {0, 2, 4, 5, 6, 8, 11};
+ std::vector<int, A> c1(a1, a1 + sizeof(a1) / sizeof(a1[0]));
+ std::vector<int, A> c2(a2, a2 + sizeof(a2) / sizeof(a2[0]));
+ swap(c1, c2);
+ assert((c1 == std::vector<int, A>(a2, a2 + sizeof(a2) / sizeof(a2[0]))));
+ assert((c2 == std::vector<int, A>(a1, a1 + sizeof(a1) / sizeof(a1[0]))));
+ }
+ {
+ int a1[] = {1, 3, 7, 9, 10};
+ int a2[] = {0, 2, 4, 5, 6, 8, 11};
+ std::vector<int, A> c1(a1, a1);
+ std::vector<int, A> c2(a2, a2 + sizeof(a2) / sizeof(a2[0]));
+ swap(c1, c2);
+ assert((c1 == std::vector<int, A>(a2, a2 + sizeof(a2) / sizeof(a2[0]))));
+ assert(c2.empty());
+ assert(std::distance(c2.begin(), c2.end()) == 0);
+ }
+ {
+ int a1[] = {1, 3, 7, 9, 10};
+ int a2[] = {0, 2, 4, 5, 6, 8, 11};
+ std::vector<int, A> c1(a1, a1 + sizeof(a1) / sizeof(a1[0]));
+ std::vector<int, A> c2(a2, a2);
+ swap(c1, c2);
+ assert(c1.empty());
+ assert(std::distance(c1.begin(), c1.end()) == 0);
+ assert((c2 == std::vector<int, A>(a1, a1 + sizeof(a1) / sizeof(a1[0]))));
+ }
+ {
+ int a1[] = {1, 3, 7, 9, 10};
+ int a2[] = {0, 2, 4, 5, 6, 8, 11};
+ std::vector<int, A> c1(a1, a1);
+ std::vector<int, A> c2(a2, a2);
+ swap(c1, c2);
+ assert(c1.empty());
+ assert(std::distance(c1.begin(), c1.end()) == 0);
+ assert(c2.empty());
+ assert(std::distance(c2.begin(), c2.end()) == 0);
+ }
+ {
+ int a1[] = {1, 3, 7, 9, 10};
+ int a2[] = {0, 2, 4, 5, 6, 8, 11};
+ std::vector<int, A> c1(a1, a1 + sizeof(a1) / sizeof(a1[0]), A());
+ std::vector<int, A> c2(a2, a2 + sizeof(a2) / sizeof(a2[0]), A());
+ swap(c1, c2);
+ assert((c1 == std::vector<int, A>(a2, a2 + sizeof(a2) / sizeof(a2[0]))));
+ assert(c1.get_allocator() == A());
+ assert((c2 == std::vector<int, A>(a1, a1 + sizeof(a1) / sizeof(a1[0]))));
+ assert(c2.get_allocator() == A());
+ }
+}
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+ {
+ int a1[] = {1, 3, 7, 9, 10};
+ int a2[] = {0, 2, 4, 5, 6, 8, 11};
+ std::vector<int> c1(a1, a1 + sizeof(a1) / sizeof(a1[0]));
+ std::vector<int> c2(a2, a2 + sizeof(a2) / sizeof(a2[0]));
+ swap(c1, c2);
+ assert(c1 == std::vector<int>(a2, a2 + sizeof(a2) / sizeof(a2[0])));
+ assert(c2 == std::vector<int>(a1, a1 + sizeof(a1) / sizeof(a1[0])));
+ }
+ {
+ int a1[] = {1, 3, 7, 9, 10};
+ int a2[] = {0, 2, 4, 5, 6, 8, 11};
+ std::vector<int> c1(a1, a1);
+ std::vector<int> c2(a2, a2 + sizeof(a2) / sizeof(a2[0]));
+ swap(c1, c2);
+ assert(c1 == std::vector<int>(a2, a2 + sizeof(a2) / sizeof(a2[0])));
+ assert(c2.empty());
+ assert(std::distance(c2.begin(), c2.end()) == 0);
+ }
+ {
+ int a1[] = {1, 3, 7, 9, 10};
+ int a2[] = {0, 2, 4, 5, 6, 8, 11};
+ std::vector<int> c1(a1, a1 + sizeof(a1) / sizeof(a1[0]));
+ std::vector<int> c2(a2, a2);
+ swap(c1, c2);
+ assert(c1.empty());
+ assert(std::distance(c1.begin(), c1.end()) == 0);
+ assert(c2 == std::vector<int>(a1, a1 + sizeof(a1) / sizeof(a1[0])));
+ }
+ {
+ int a1[] = {1, 3, 7, 9, 10};
+ int a2[] = {0, 2, 4, 5, 6, 8, 11};
+ std::vector<int> c1(a1, a1);
+ std::vector<int> c2(a2, a2);
+ swap(c1, c2);
+ assert(c1.empty());
+ assert(std::distance(c1.begin(), c1.end()) == 0);
+ assert(c2.empty());
+ assert(std::distance(c2.begin(), c2.end()) == 0);
+ }
+ {
+ int a1[] = {1, 3, 7, 9, 10};
+ int a2[] = {0, 2, 4, 5, 6, 8, 11};
+ typedef test_allocator<int> A;
+ std::vector<int, A> c1(a1, a1 + sizeof(a1) / sizeof(a1[0]), A(1, 1));
+ std::vector<int, A> c2(a2, a2 + sizeof(a2) / sizeof(a2[0]), A(1, 2));
+ swap(c1, c2);
+ assert((c1 == std::vector<int, A>(a2, a2 + sizeof(a2) / sizeof(a2[0]))));
+ assert(c1.get_allocator().get_id() == 1);
+ assert((c2 == std::vector<int, A>(a1, a1 + sizeof(a1) / sizeof(a1[0]))));
+ assert(c2.get_allocator().get_id() == 2);
+ }
+ {
+ int a1[] = {1, 3, 7, 9, 10};
+ int a2[] = {0, 2, 4, 5, 6, 8, 11};
+ typedef other_allocator<int> A;
+ std::vector<int, A> c1(a1, a1 + sizeof(a1) / sizeof(a1[0]), A(1));
+ std::vector<int, A> c2(a2, a2 + sizeof(a2) / sizeof(a2[0]), A(2));
+ swap(c1, c2);
+ assert((c1 == std::vector<int, A>(a2, a2 + sizeof(a2) / sizeof(a2[0]))));
+ assert(c1.get_allocator() == A(2));
+ assert((c2 == std::vector<int, A>(a1, a1 + sizeof(a1) / sizeof(a1[0]))));
+ assert(c2.get_allocator() == A(1));
+ }
+#if TEST_STD_VER >= 11
+ test_with_allocator<min_allocator<int>>();
+ test_with_allocator<safe_allocator<int>>();
+#endif
+
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+#if TEST_STD_VER > 17
+ static_assert(tests());
+#endif
+ return 0;
+}
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/inplace_vector.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/inplace_vector.version.compile.pass.cpp
new file mode 100644
index 00000000000000..ea4409cac91626
--- /dev/null
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/inplace_vector.version.compile.pass.cpp
@@ -0,0 +1,65 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// WARNING: This test was generated by generate_feature_test_macro_components.py
+// and should not be edited manually.
+//
+// clang-format off
+
+// <inplace_vector>
+
+// Test the feature test macros defined by <inplace_vector>
+
+/* Constant Value
+ __cpp_lib_inplace_vector 202406L [C++26]
+*/
+
+#include <inplace_vector>
+#include "test_macros.h"
+
+#if TEST_STD_VER < 14
+
+# ifdef __cpp_lib_inplace_vector
+# error "__cpp_lib_inplace_vector should not be defined before c++26"
+# endif
+
+#elif TEST_STD_VER == 14
+
+# ifdef __cpp_lib_inplace_vector
+# error "__cpp_lib_inplace_vector should not be defined before c++26"
+# endif
+
+#elif TEST_STD_VER == 17
+
+# ifdef __cpp_lib_inplace_vector
+# error "__cpp_lib_inplace_vector should not be defined before c++26"
+# endif
+
+#elif TEST_STD_VER == 20
+
+# ifdef __cpp_lib_inplace_vector
+# error "__cpp_lib_inplace_vector should not be defined before c++26"
+# endif
+
+#elif TEST_STD_VER == 23
+
+# ifdef __cpp_lib_inplace_vector
+# error "__cpp_lib_inplace_vector should not be defined before c++26"
+# endif
+
+#elif TEST_STD_VER > 23
+
+# ifndef __cpp_lib_inplace_vector
+# error "__cpp_lib_inplace_vector should be defined in c++26"
+# endif
+# if __cpp_lib_inplace_vector != 202406L
+# error "__cpp_lib_inplace_vector should have the value 202406L in c++26"
+# endif
+
+#endif // TEST_STD_VER > 23
+
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
index 985ffeffab96db..de4df21e745097 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
@@ -7022,17 +7022,11 @@
# error "__cpp_lib_incomplete_container_elements should have the value 201505L in c++26"
# endif
-# if !defined(_LIBCPP_VERSION)
-# ifndef __cpp_lib_inplace_vector
-# error "__cpp_lib_inplace_vector should be defined in c++26"
-# endif
-# if __cpp_lib_inplace_vector != 202406L
-# error "__cpp_lib_inplace_vector should have the value 202406L in c++26"
-# endif
-# else // _LIBCPP_VERSION
-# ifdef __cpp_lib_inplace_vector
-# error "__cpp_lib_inplace_vector should not be defined because it is unimplemented in libc++!"
-# endif
+# ifndef __cpp_lib_inplace_vector
+# error "__cpp_lib_inplace_vector should be defined in c++26"
+# endif
+# if __cpp_lib_inplace_vector != 202406L
+# error "__cpp_lib_inplace_vector should have the value 202406L in c++26"
# endif
# ifndef __cpp_lib_int_pow2
diff --git a/libcxx/test/support/test_container_comparisons.h b/libcxx/test/support/test_container_comparisons.h
index 543c5899922d02..e72efc39a8ad92 100644
--- a/libcxx/test/support/test_container_comparisons.h
+++ b/libcxx/test/support/test_container_comparisons.h
@@ -12,18 +12,53 @@
#include <functional>
#include <set>
+#include <cstddef>
+#include <type_traits>
+#include "test_macros.h"
#include "test_comparisons.h"
+#if TEST_STD_VER >= 26
+# include <inplace_vector>
+
+template <typename C>
+concept is_inplace_vector = std::is_same_v<C, std::inplace_vector<typename C::value_type, C::capacity()>>;
+#else
+template <typename C>
+concept is_inplace_vector = false;
+#endif
+
+template <typename C>
+constexpr bool can_run() {
+ if constexpr (is_inplace_vector<C>) {
+ if consteval {
+ return std::is_trivial_v<typename C::value_type>;
+ }
+ }
+ return true;
+}
+
+template <typename C>
+constexpr std::size_t get_max_size() {
+ if constexpr (is_inplace_vector<C>) {
+ return C::max_size();
+ }
+ return static_cast<std::size_t>(-1);
+}
+
// Implementation detail of `test_sequence_container_spaceship`
template <template <typename...> typename Container, typename Elem, typename Order>
constexpr void test_sequence_container_spaceship_with_type() {
+ if (!can_run<Container<Elem>>())
+ return;
// Empty containers
{
Container<Elem> l1;
Container<Elem> l2;
assert(testOrder(l1, l2, Order::equivalent));
}
+ if (get_max_size<Container<Elem>>() < 2)
+ return;
// Identical contents
{
Container<Elem> l1{1, 1};
@@ -91,6 +126,8 @@ template <template <typename...> typename ContainerAdaptor,
typename Elem,
typename Order>
constexpr void test_sequence_container_adaptor_spaceship_with_type() {
+ if (!can_run<Container<Elem>>())
+ return;
// Empty containers
{
Container<Elem> l1;
@@ -99,6 +136,8 @@ constexpr void test_sequence_container_adaptor_spaceship_with_type() {
ContainerAdaptor<Elem, Container<Elem>> ca2{l2};
assert(testOrder(ca1, ca2, Order::equivalent));
}
+ if (get_max_size<Container<Elem>>() < 2)
+ return;
// Identical contents
{
Container<Elem> l1{1, 1};
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index cb5ff770b1196e..b6e70f7c284b3b 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -685,7 +685,6 @@ def add_version_header(tc):
"name": "__cpp_lib_inplace_vector",
"values": {"c++26": 202406}, # P0843R14 inplace_vector
"headers": ["inplace_vector"],
- "unimplemented": True,
},
{
"name": "__cpp_lib_int_pow2",
diff --git a/libcxx/utils/libcxx/header_information.py b/libcxx/utils/libcxx/header_information.py
index fd48b35a88b558..8d1eb481c57a71 100644
--- a/libcxx/utils/libcxx/header_information.py
+++ b/libcxx/utils/libcxx/header_information.py
@@ -86,6 +86,7 @@
"deque": ["compare", "initializer_list"],
"filesystem": ["compare"],
"forward_list": ["compare", "initializer_list"],
+ "inplace_vector": ["compare", "initializer_list"],
"ios": ["iosfwd"],
"iostream": ["ios", "istream", "ostream", "streambuf"],
"iterator": ["compare", "concepts"],
@@ -127,7 +128,6 @@
"flat_set",
"generator",
"hazard_pointer",
- "inplace_vector",
"linalg",
"rcu",
"spanstream",
More information about the libcxx-commits
mailing list