[libcxx-commits] [libcxx] [libc++] Implement `std::inplace_vector<T, N>` (PR #105981)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Nov 8 04:25:00 PST 2024
================
@@ -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))) {
----------------
philnik777 wrote:
```suggestion
} else if constexpr (_Capacity <= numeric_limits<unsigned char>::max() && (sizeof(unsigned char) < sizeof(size_t))) {
```
Why do you check for `sizeof(T) < sizeof(size_t)`? It's not like we care in the end which type exactly is used.
https://github.com/llvm/llvm-project/pull/105981
More information about the libcxx-commits
mailing list