1// Sequence container with fixed capacity -*- C++ -*-
3// Copyright The GNU Toolchain Authors.
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
25/** @file include/inplace_vector
26 * This is a Standard C++ Library header.
30#ifndef _GLIBCXX_INPLACE_VECTOR
31#define _GLIBCXX_INPLACE_VECTOR 1
33#pragma GCC system_header
35#define __glibcxx_want_inplace_vector
36#include <bits/version.h>
38#ifdef __glibcxx_inplace_vector // C++ >= 26
40#include <initializer_list>
41#include <bits/range_access.h>
42#include <bits/ranges_base.h> // borrowed_iterator_t, __detail::__container_compatible_range
43#include <bits/ranges_util.h> // subrange
44#include <bits/ranges_uninitialized.h>
45#include <bits/refwrap.h>
46#include <bits/stl_construct.h>
47#include <bits/stl_uninitialized.h>
48#include <bits/stl_algo.h> // rotate
50namespace std _GLIBCXX_VISIBILITY(default)
52_GLIBCXX_BEGIN_NAMESPACE_VERSION
54 // [indirect], class template indirect
55 template<typename _Tp, size_t _Nm>
61 using value_type = _Tp;
63 using const_pointer = const _Tp*;
64 using reference = value_type&;
65 using const_reference = const value_type&;
66 using size_type = size_t;
67 using difference_type = ptrdiff_t;
69 = __gnu_cxx::__normal_iterator<_Tp*, inplace_vector>;
71 = __gnu_cxx::__normal_iterator<const _Tp*, inplace_vector>;
72 using reverse_iterator = std::reverse_iterator<iterator>;
73 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
75 // [containers.sequences.inplace.vector.cons], construct/copy/destroy
77 inplace_vector() noexcept
81 inplace_vector(size_type __n)
85 std::uninitialized_value_construct_n(data(), __n);
90 inplace_vector(size_type __n, const _Tp& __value)
94 std::uninitialized_fill_n(data(), __n, __value);
98 template<__any_input_iterator _InputIterator>
100 inplace_vector(_InputIterator __first, _InputIterator __last)
103 if (const auto __n = _S_distance(__first, __last))
106 std::uninitialized_copy(__first, __last, data());
111 while (__first != __last)
112 emplace_back(*__first++);
116 template <__detail::__container_compatible_range<_Tp> _Rg>
118 inplace_vector(from_range_t, _Rg&& __rg)
120 { append_range(__rg); }
123 inplace_vector(initializer_list<_Tp> __il)
126 _S_reserve(__il.size());
127 std::uninitialized_copy(__il.begin(), __il.end(), data());
128 _M_size = __il.size();
131 inplace_vector(const inplace_vector&)
132 requires is_trivially_copy_constructible_v<_Tp>
136 inplace_vector(const inplace_vector& __other)
137 noexcept(is_nothrow_copy_constructible_v<_Tp>)
140 std::uninitialized_copy(__other.begin(), __other.end(), data());
141 _M_size = __other.size();
144 inplace_vector(inplace_vector&&)
145 requires is_trivially_move_constructible_v<_Tp>
149 inplace_vector(inplace_vector&& __other)
150 noexcept(is_nothrow_move_constructible_v<_Tp>)
153 std::uninitialized_move(__other.begin(), __other.end(), data());
154 _M_size = __other.size();
158 requires is_trivially_destructible_v<_Tp>
166 operator=(const inplace_vector&)
167 requires is_trivially_copy_assignable_v<_Tp>
168 && is_trivially_copy_constructible_v<_Tp>
169 && is_trivially_destructible_v<_Tp>
172 constexpr inplace_vector&
173 operator=(const inplace_vector& __other)
174 noexcept(is_nothrow_copy_assignable_v<_Tp>
175 && is_nothrow_copy_constructible_v<_Tp>)
177 if (std::addressof(__other) != this) [[likely]]
178 assign(__other.begin(), __other.end());
183 operator=(inplace_vector&&)
184 requires is_trivially_move_assignable_v<_Tp>
185 && is_trivially_move_constructible_v<_Tp>
186 && is_trivially_destructible_v<_Tp>
189 constexpr inplace_vector&
190 operator=(inplace_vector&& __other)
191 noexcept(is_nothrow_move_assignable_v<_Tp>
192 && is_nothrow_move_constructible_v<_Tp>)
194 if (std::addressof(__other) != this) [[likely]]
195 assign(std::make_move_iterator(__other.begin()),
196 std::make_move_iterator(__other.end()));
200 constexpr inplace_vector&
201 operator=(initializer_list<_Tp> __il)
203 assign(__il.begin(), __il.end());
207 template<__any_input_iterator _InputIterator>
209 assign(_InputIterator __first, _InputIterator __last)
211 if (const auto __n = _S_distance(__first, __last))
216 for (size_t __i = 0; __i < _M_size; ++__i, (void)++__first)
217 _M_elems[__i] = *__first;
218 std::uninitialized_copy(__first, __last, end());
221 std::destroy(std::copy(__first, __last, begin()), end());
227 for (;__first != __last && __i < _M_size; ++__first)
228 _M_elems[__i++] = *__first;
229 if (__first == __last)
231 std::_Destroy_n(data() + __i, _M_size - __i);
236 while (__first != __last)
237 emplace_back(*__first++);
242 template<__detail::__container_compatible_range<_Tp> _Rg>
244 assign_range(_Rg&& __rg)
246 if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
248 const auto __sz = ranges::distance(__rg);
253 ranges::copy_n(ranges::begin(__rg), __sz, data());
254 std::destroy(data() + __sz, data() + _M_size);
258 auto [__in, __out] = ranges::copy_n(
259 ranges::begin(__rg), _M_size,
261 ranges::uninitialized_copy(
262 std::move(__in), ranges::end(__rg),
263 __out, unreachable_sentinel);
269 auto __in = ranges::begin(__rg);
270 auto __end = ranges::end(__rg);
272 for (; __n < _M_size && __in != __end; ++__in)
273 _M_elems[__n++] = *__in;
277 std::destroy(data() + __n, data() + _M_size);
283 auto __res = ranges::uninitialized_copy(
284 std::move(__in), __end,
285 data() + __n, data() + _Nm);
286 _M_size = __res.out - data();
287 if (__res.in == ranges::end(__rg))
295 assign(size_type __n, const _Tp& __u)
299 std::uninitialized_fill_n(std::fill_n(data(), _M_size, __u),
302 std::destroy_n(std::fill_n(data(), __n, __u), _M_size - __n);
307 assign(initializer_list<_Tp> __il)
308 { assign(__il.begin(), __il.end()); }
313 begin() noexcept { return iterator(data()); }
316 constexpr const_iterator
317 begin() const noexcept { return const_iterator(data()); }
322 { return iterator(data() + _M_size); }
325 constexpr const_iterator
327 { return const_iterator(data() + _M_size); }
330 constexpr reverse_iterator
332 { return reverse_iterator(end()); }
335 constexpr const_reverse_iterator
336 rbegin() const noexcept
337 { return const_reverse_iterator(end()); }
340 constexpr reverse_iterator
341 rend() noexcept { return reverse_iterator(begin()); }
344 constexpr const_reverse_iterator
345 rend() const noexcept { return const_reverse_iterator(begin()); }
348 constexpr const_iterator
349 cbegin() const noexcept { return begin(); }
352 constexpr const_iterator
353 cend() const noexcept { return end(); }
356 constexpr const_reverse_iterator
357 crbegin() const noexcept { return rbegin(); }
360 constexpr const_reverse_iterator
361 crend() const noexcept { return rend(); }
363 // [containers.sequences.inplace.vector.members] size/capacity
366 empty() const noexcept { return _M_size == 0; }
370 size() const noexcept
373 __builtin_unreachable();
378 static constexpr size_type
379 max_size() noexcept { return _Nm; }
382 static constexpr size_type
383 capacity() noexcept { return _Nm; }
386 resize(size_type __n)
390 std::uninitialized_value_construct_n(data() + _M_size, __n - _M_size);
391 else if (__n < _M_size)
392 std::destroy_n(data() + __n, _M_size - __n);
397 resize(size_type __n, const _Tp& __c)
401 std::uninitialized_fill_n(data() + _M_size, __n - _M_size, __c);
402 else if (__n < _M_size)
403 std::destroy_n(data() + __n, _M_size - __n);
407 static constexpr void
408 reserve(size_type __n)
411 static constexpr void
417 operator[](size_type __n)
419 __glibcxx_requires_subscript(__n);
420 return _M_elems[__n];
424 constexpr const_reference
425 operator[](size_type __n) const
427 __glibcxx_requires_subscript(__n);
428 return _M_elems[__n];
432 constexpr const_reference
433 at(size_type __n) const
436 std::__throw_out_of_range_fmt(__N("inplace_vector::at: __n "
438 ">= size() (which is %zu)"),
440 return _M_elems[__n];
448 std::__throw_out_of_range_fmt(__N("inplace_vector::at: __n "
450 ">= size() (which is %zu)"),
452 return _M_elems[__n];
459 __glibcxx_requires_nonempty();
464 constexpr const_reference
467 __glibcxx_requires_nonempty();
475 __glibcxx_requires_nonempty();
476 return _M_elems[_M_size - 1];
480 constexpr const_reference
483 __glibcxx_requires_nonempty();
484 return _M_elems[_M_size - 1];
487 // [containers.sequences.inplace.vector.data], data access
492 { return static_cast<pointer>(_M_elems); }
496 data() const noexcept
497 { return static_cast<const_pointer>(_M_elems); }
499 // [containers.sequences.inplace.vector.modifiers], modifiers
500 template<typename... _Args>
502 emplace_back(_Args&&... __args)
506 return unchecked_emplace_back(std::forward<_Args>(__args)...);
510 push_back(const _Tp& __x)
511 { return emplace_back(__x); }
515 { return emplace_back(std::move(__x)); }
517 template<__detail::__container_compatible_range<_Tp> _Rg>
519 append_range(_Rg&& __rg)
521 if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
523 const auto __sz = ranges::distance(__rg);
524 if (__sz > (_Nm - size()))
526 // Bounded on output range due PR121143
527 ranges::uninitialized_copy(
528 ranges::begin(__rg), unreachable_sentinel,
529 data() + _M_size, data() + _M_size + __sz);
530 _M_size += size_type(__sz);
534 ranges::subrange<pointer> __tail(data() + _M_size, data() + _Nm);
535 auto [__in, __out] = ranges::uninitialized_copy(__rg, __tail);
536 _M_size = __out - data();
537 if (__in != ranges::end(__rg))
545 __glibcxx_requires_nonempty();
547 _M_elems[_M_size].~_Tp();
550 template<typename... _Args>
552 try_emplace_back(_Args&&... __args)
554 if (_M_size >= _Nm) [[unlikely]]
556 auto& __r = unchecked_emplace_back(std::forward<_Args>(__args)...);
557 return __builtin_addressof(__r);
561 try_push_back(const _Tp& __x)
563 if (_M_size >= _Nm) [[unlikely]]
565 return __builtin_addressof(unchecked_emplace_back(__x));
569 try_push_back(_Tp&& __x)
571 if (_M_size >= _Nm) [[unlikely]]
573 return __builtin_addressof(unchecked_emplace_back(std::move(__x)));
576 template<__detail::__container_compatible_range<_Tp> _Rg>
577 constexpr ranges::borrowed_iterator_t<_Rg>
578 try_append_range(_Rg&& __rg)
580 if constexpr (ranges::sized_range<_Rg>)
582 auto __n = ranges::distance(__rg);
583 if (__n == 0) [[unlikely]]
584 return ranges::begin(__rg);
586 const auto __end = data() + _M_size;
587 const size_t __avail = _Nm - size();
589 _M_size += size_type(__n);
595 return ranges::uninitialized_copy_n(
596 ranges::begin(__rg), __n,
597 __end, unreachable_sentinel).in;
601 ranges::subrange<pointer> __tail(data() + _M_size, data() + _Nm);
602 auto [__in, __out] = ranges::uninitialized_copy(__rg, __tail);
603 _M_size = __out - data();
604 return std::move(__in);
608 template<typename... _Args>
610 unchecked_emplace_back(_Args&&... __args)
612 __glibcxx_assert(_M_size < _Nm);
613 auto __p = std::construct_at(data() + _M_size,
614 std::forward<_Args>(__args)...);
620 unchecked_push_back(const _Tp& __x)
621 { return unchecked_emplace_back(__x); }
624 unchecked_push_back(_Tp&& __x)
625 { return unchecked_emplace_back(std::move(__x)); }
627 template<typename... _Args>
629 emplace(const_iterator __position, _Args&&... __args)
631 size_t __b = __position - cbegin(); // elements before position
632 __glibcxx_assert(__b <= _M_size);
635 iterator __pos = begin() + __b;
636 std::construct_at(data() + _M_size, std::forward<_Args>(__args)...);
638 std::rotate(__pos, end() - 1, end());
643 insert(const_iterator __position, const _Tp& __x)
644 { return emplace(__position, __x); }
647 insert(const_iterator __position, _Tp&& __x)
648 { return emplace(__position, std::move(__x)); }
651 insert(const_iterator __position, size_type __n, const _Tp& __x)
653 size_t __b = __position - cbegin(); // elements before position
654 __glibcxx_assert(__b <= _M_size);
655 if ((_Nm - _M_size) < __n)
657 iterator __pos = begin() + __b;
658 std::uninitialized_fill_n(data() + _M_size, __n, __x);
659 if (std::__exchange(_M_size, _M_size + __n))
660 std::rotate(__pos, end() - __n, end());
664 template<__any_input_iterator _InputIterator>
666 insert(const_iterator __position, _InputIterator __first,
667 _InputIterator __last)
669 size_t __b = __position - cbegin(); // elements before position
670 __glibcxx_assert(__b <= _M_size);
671 iterator __pos = begin() + __b;
672 const size_t __s = _M_size;
673 if (const auto __n = _S_distance(__first, __last))
675 if ((_Nm - _M_size) < __n)
677 std::uninitialized_copy(__first, __last, data() + _M_size);
682 while (__first != __last)
683 emplace_back(*__first++);
686 std::rotate(__pos, begin() + __s, end());
690 template<__detail::__container_compatible_range<_Tp> _Rg>
692 insert_range(const_iterator __position, _Rg&& __rg)
694 iterator __pos = begin() + (__position - cbegin());
695 const auto __end = end();
696 if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
698 const auto __len = ranges::distance(__rg);
699 if (__len > (_Nm - size()))
701 if (!__len) [[unlikely]]
704 const size_type __n = size_type(__len);
705 const size_type __num_after = __end - __pos;
706 if (__num_after >= __n)
708 ranges::uninitialized_move(__end - __n, __end,
709 __end, unreachable_sentinel);
711 ranges::move_backward(__pos, __end - __n, __end);
712 ranges::copy(__rg, __pos);
714 else if constexpr (ranges::forward_range<_Rg>)
716 auto __mid = ranges::next(ranges::begin(__rg), __num_after);
717 ranges::uninitialized_copy(__mid, ranges::end(__rg),
718 __end, unreachable_sentinel);
719 _M_size += __n - __num_after;
720 ranges::uninitialized_move(__pos, __end,
721 __pos + __n, unreachable_sentinel);
722 _M_size += __num_after;
723 ranges::copy(ranges::begin(__rg), __mid, __pos);
727 ranges::uninitialized_copy(
728 ranges::begin(__rg), ranges::end(__rg),
729 __end, unreachable_sentinel);
731 std::rotate(__pos, __end, end());
737 std::rotate(__pos, __end, end());
743 insert(const_iterator __position, initializer_list<_Tp> __il)
744 { return insert(__position, __il.begin(), __il.end()); }
747 erase(const_iterator __position)
749 size_t __n = __position - cbegin();
750 __glibcxx_assert(__n < _M_size);
751 iterator __pos = begin() + __n;
752 std::move(__pos + 1, end(), __pos);
758 erase(const_iterator __first, const_iterator __last)
760 size_t __n = __first - cbegin();
761 size_t __x = __last - __first;
762 __glibcxx_assert(__n <= _M_size);
763 __glibcxx_assert(__x <= _M_size);
764 iterator __pos = begin() + __n;
765 iterator __end = std::move(__pos + __x, end(), __pos);
766 std::destroy_n(__end, __x);
772 swap(inplace_vector& __x)
773 noexcept(is_nothrow_swappable_v<_Tp> && is_nothrow_move_constructible_v<_Tp>)
775 inplace_vector* __vs[2]{ this, std::addressof(__x) };
776 const auto __smaller = __vs[__x.size() < size()];
777 const auto __bigger = __vs[__x.size() >= size()];
778 size_type __n = __smaller->size();
779 size_type __n2 = __bigger->size();
781 if constexpr (is_nothrow_move_constructible_v<_Tp>)
783 for (size_type __i = __n; __i < __n2; ++__i)
785 std::construct_at(__smaller->data() + __i,
786 std::move(*(__bigger->data() + __i)));
787 std::destroy_at(__bigger->data() + __i);
792 std::uninitialized_copy(__bigger->data() + __n,
793 __bigger->data() + __n2,
794 __smaller->data() + __n);
795 std::destroy(__bigger->data() + __n, __bigger->data() + __n2);
797 __smaller->_M_size = __n2;
798 __bigger->_M_size = __n;
801 for (size_type __i = 0; __i < __n; __i++)
802 swap(_M_elems[__i], __x._M_elems[__i]);
808 std::destroy_n(data(), size_t(_M_size));
812 constexpr friend bool
813 operator==(const inplace_vector& __x, const inplace_vector& __y)
814 { return std::equal(__x.begin(), __x.end(), __y.begin(), __y.end()); }
816 constexpr friend auto
817 operator<=>(const inplace_vector& __x, const inplace_vector& __y)
818 requires requires (const _Tp __t) {
819 { __t < __t } -> __detail::__boolean_testable;
822 return std::lexicographical_compare_three_way(__x.begin(), __x.end(),
823 __y.begin(), __y.end(),
824 __detail::__synth3way);
827 constexpr friend void
828 swap(inplace_vector& __x, inplace_vector& __y)
829 noexcept(is_nothrow_swappable_v<_Tp> && is_nothrow_move_constructible_v<_Tp>)
837 // Check whether integer type _UInt is wide enough to store _Nm,
838 // so that we use a smaller type for _M_size when that saves space.
839 template<typename _UInt, bool = (alignof(_Tp) <= sizeof(_UInt))>
840 static constexpr bool __fits
841 = _Nm <= __gnu_cxx::__int_traits<_UInt>::__max;
843 // Don't bother using a smaller type if alignment of the array elements
844 // means that it doesn't actually save space.
845 template<typename _UInt>
846 static constexpr bool __fits<_UInt, false> = false;
848 static consteval auto __select_size_type()
850 if constexpr (__fits<unsigned char>)
851 return (unsigned char)0;
852#if __SHRT_WIDTH__ < __SIZE_WIDTH__
853 else if constexpr (__fits<unsigned short>)
854 return (unsigned short)0;
856#if __INT_WIDTH__ < __SIZE_WIDTH__ && __INT_WIDTH__ > __SHRT_WIDTH__
857 else if constexpr (__fits<unsigned int>)
860#if __LONG_WIDTH__ < __SIZE_WIDTH__ && __LONG_WIDTH__ > __INT_WIDTH__
861 else if constexpr (__fits<unsigned long>)
864 else // Just use size_t.
867 decltype(__select_size_type()) _M_size = 0;
874#if __glibcxx_start_lifetime_as
875 std::start_lifetime_as_array<_Tp>(data(), _Nm);
880 // TODO: use new(_M_elems) _Tp[_Nm]() once PR121068 is fixed
881 if constexpr (is_trivial_v<_Tp>)
882 for (size_t __i = 0; __i < _Nm; ++__i)
883 _M_elems[__i] = _Tp();
885 __builtin_unreachable(); // only trivial types are supported at compile time
889 static constexpr void
890 _S_reserve(size_t __n)
896 template<typename _InputIterator>
897 constexpr static auto
898 _S_distance(_InputIterator __first, _InputIterator __last)
900 if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>
901 || forward_iterator<_InputIterator>)
902 return (size_type)ranges::distance(__first, __last);
903 else if constexpr (derived_from<__iter_category_t<_InputIterator>,
904 forward_iterator_tag>)
905 return (size_type)std::distance(__first, __last);
911 // [inplace.vector.special], specialized algorithms
912 template<typename _Tp, size_t _Nm>
914 swap(inplace_vector<_Tp, _Nm>& __x, inplace_vector<_Tp, _Nm>& __y)
915 noexcept(noexcept(__x.swap(__y)))
918 // specialization for zero capacity, that is required to be trivally copyable
919 // and empty regardless of _Tp.
920 template<typename _Tp>
921 class inplace_vector<_Tp, 0>
925 using value_type = _Tp;
926 using pointer = _Tp*;
927 using const_pointer = const _Tp*;
928 using reference = value_type&;
929 using const_reference = const value_type&;
930 using size_type = size_t;
931 using difference_type = ptrdiff_t;
933 = __gnu_cxx::__normal_iterator<_Tp*, inplace_vector>;
935 = __gnu_cxx::__normal_iterator<const _Tp*, inplace_vector>;
936 using reverse_iterator = std::reverse_iterator<iterator>;
937 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
939 // [containers.sequences.inplace.vector.cons], construct/copy/destroy
940 inplace_vector() = default;
943 inplace_vector(size_type __n)
950 inplace_vector(size_type __n, const _Tp& __value)
956 template<__any_input_iterator _InputIterator>
958 inplace_vector(_InputIterator __first, _InputIterator __last)
960 if (__first != __last)
964 template <__detail::__container_compatible_range<_Tp> _Rg>
966 inplace_vector(from_range_t, _Rg&& __rg)
968 if (ranges::begin(__rg) != ranges::end(__rg))
973 inplace_vector(initializer_list<_Tp> __il)
975 if (__il.size() != 0)
979 inplace_vector(const inplace_vector&) = default;
980 inplace_vector(inplace_vector&&) = default;
983 ~inplace_vector() = default;
986 operator=(const inplace_vector&) = default;
989 operator=(inplace_vector&&) = default;
991 constexpr inplace_vector&
992 operator=(initializer_list<_Tp> __il)
994 if (__il.size() != 0)
998 template<__any_input_iterator _InputIterator>
1000 assign(_InputIterator __first, _InputIterator __last)
1002 if (__first != __last)
1003 __throw_bad_alloc();
1006 template<__detail::__container_compatible_range<_Tp> _Rg>
1008 assign_range(_Rg&& __rg)
1010 if (ranges::begin(__rg) != ranges::end(__rg))
1011 __throw_bad_alloc();
1015 assign(size_type __n, const _Tp& __u)
1018 __throw_bad_alloc();
1022 assign(initializer_list<_Tp> __il)
1024 if (__il.size() != 0)
1025 __throw_bad_alloc();
1031 begin() noexcept { return iterator(nullptr); }
1034 constexpr const_iterator
1035 begin() const noexcept { return const_iterator(nullptr); }
1039 end() noexcept { return iterator(nullptr); }
1042 constexpr const_iterator
1043 end() const noexcept { return const_iterator(nullptr); }
1046 constexpr reverse_iterator
1048 { return reverse_iterator(end()); }
1051 constexpr const_reverse_iterator
1052 rbegin() const noexcept
1053 { return const_reverse_iterator(end()); }
1056 constexpr reverse_iterator
1057 rend() noexcept { return reverse_iterator(begin()); }
1060 constexpr const_reverse_iterator
1061 rend() const noexcept { return const_reverse_iterator(begin()); }
1064 constexpr const_iterator
1065 cbegin() const noexcept { return begin(); }
1068 constexpr const_iterator
1069 cend() const noexcept { return end(); }
1072 constexpr const_reverse_iterator
1073 crbegin() const noexcept { return rbegin(); }
1076 constexpr const_reverse_iterator
1077 crend() const noexcept { return rend(); }
1079 // [containers.sequences.inplace.vector.members] size/capacity
1082 empty() const noexcept { return true; }
1086 size() const noexcept { return 0; }
1089 static constexpr size_type
1090 max_size() noexcept { return 0; }
1093 static constexpr size_type
1094 capacity() noexcept { return 0; }
1097 resize(size_type __n)
1100 __throw_bad_alloc();
1104 resize(size_type __n, const _Tp&)
1107 __throw_bad_alloc();
1110 static constexpr void
1111 reserve(size_type __n)
1114 __throw_bad_alloc();
1117 static constexpr void
1121 [[nodiscard,noreturn]]
1123 operator[](size_type)
1124 { __builtin_trap(); }
1126 [[nodiscard,noreturn]]
1127 constexpr const_reference
1128 operator[](size_type) const
1129 { __builtin_trap(); }
1131 [[nodiscard,noreturn]]
1132 constexpr const_reference
1133 at(size_type __n) const
1135 std::__throw_out_of_range_fmt(__N("inplace_vector::at: __n "
1137 ">= size() (which is 0)"),
1141 [[nodiscard,noreturn]]
1145 std::__throw_out_of_range_fmt(__N("inplace_vector::at: __n "
1147 ">= size() (which is 0)"),
1151 [[nodiscard,noreturn]]
1154 { __builtin_trap(); }
1156 [[nodiscard,noreturn]]
1157 constexpr const_reference
1159 { __builtin_trap(); }
1161 [[nodiscard,noreturn]]
1164 { __builtin_trap(); }
1166 [[nodiscard,noreturn]]
1167 constexpr const_reference
1169 { __builtin_trap(); }
1171 // [containers.sequences.inplace.vector.data], data access
1179 constexpr const _Tp*
1180 data() const noexcept
1183 // [containers.sequences.inplace.vector.modifiers], modifiers
1184 template<typename... _Args>
1187 emplace_back(_Args&&...)
1188 { __throw_bad_alloc(); }
1192 push_back(const _Tp&)
1193 { __throw_bad_alloc(); }
1198 { __throw_bad_alloc(); }
1200 template<__detail::__container_compatible_range<_Tp> _Rg>
1202 append_range(_Rg&& __rg)
1204 if (ranges::begin(__rg) != ranges::end(__rg))
1205 __throw_bad_alloc();
1211 { __builtin_trap(); }
1213 template<typename... _Args>
1215 try_emplace_back(_Args&&...)
1219 try_push_back(const _Tp&)
1223 try_push_back(_Tp&&)
1226 template<__detail::__container_compatible_range<_Tp> _Rg>
1227 constexpr ranges::borrowed_iterator_t<_Rg>
1228 try_append_range(_Rg&& __rg)
1229 { return ranges::begin(__rg); }
1231 template<typename... _Args>
1234 unchecked_emplace_back(_Args&&...)
1235 { __builtin_trap(); }
1239 unchecked_push_back(const _Tp&)
1240 { __builtin_trap(); }
1244 unchecked_push_back(_Tp&&)
1245 { __builtin_trap(); }
1247 template<typename... _Args>
1250 emplace(const_iterator, _Args&&...)
1251 { __throw_bad_alloc(); }
1255 insert(const_iterator, const _Tp&)
1256 { __throw_bad_alloc(); }
1260 insert(const_iterator, _Tp&&)
1261 { __throw_bad_alloc(); }
1264 insert(const_iterator, size_type __n, const _Tp&)
1267 __throw_bad_alloc();
1271 template<typename _InputIterator>
1273 insert(const_iterator, _InputIterator __first, _InputIterator __last)
1275 if (__first != __last)
1276 __throw_bad_alloc();
1280 template<__detail::__container_compatible_range<_Tp> _Rg>
1282 insert_range(const_iterator, _Rg&& __rg)
1284 if (ranges::begin(__rg) != ranges::end(__rg))
1285 __throw_bad_alloc();
1290 insert(const_iterator, initializer_list<_Tp> __il)
1292 if (__il.size() != 0)
1293 __throw_bad_alloc();
1299 erase(const_iterator)
1300 { __builtin_trap(); }
1303 erase(const_iterator __first, const_iterator __last)
1305 __glibcxx_assert(__first == __last);
1310 swap(inplace_vector& __x)
1318 constexpr friend bool
1319 operator==(const inplace_vector&, const inplace_vector&)
1322 constexpr friend auto
1323 operator<=>(const inplace_vector&, const inplace_vector&)
1324 requires requires (const _Tp __t) {
1325 { __t < __t } -> __detail::__boolean_testable;
1327 { return std::strong_ordering::equal; }
1329 // n.b. there is not explicit wording requiring that swap for inplace_vector,
1330 // with zero size, works even if element type is not swappable. However given
1331 // that move operations are required to be present and trivial, it makes sense
1333 constexpr friend void
1334 swap(inplace_vector&, inplace_vector&) noexcept
1338 template<typename _Tp, size_t _Nm, typename _Predicate>
1340 erase_if(inplace_vector<_Tp, _Nm>& __cont, _Predicate __pred)
1342 using namespace __gnu_cxx;
1343 const auto __osz = __cont.size();
1344 const auto __end = __cont.end();
1345 auto __removed = std::__remove_if(__cont.begin(), __end,
1346 __ops::__pred_iter(std::ref(__pred)));
1347 if (__removed != __end)
1349 __cont.erase(__niter_wrap(__cont.begin(), __removed),
1351 return __osz - __cont.size();
1357 template<typename _Tp, size_t _Nm, typename _Up = _Tp>
1359 erase(inplace_vector<_Tp, _Nm>& __cont, const _Up& __value)
1361 using namespace __gnu_cxx;
1362 const auto __osz = __cont.size();
1363 const auto __end = __cont.end();
1364 auto __removed = std::__remove_if(__cont.begin(), __end,
1365 __ops::__iter_equals_val(__value));
1366 if (__removed != __end)
1368 __cont.erase(__niter_wrap(__cont.begin(), __removed),
1370 return __osz - __cont.size();
1375_GLIBCXX_END_NAMESPACE_VERSION
1378#endif // __glibcxx_inplace_vector
1379#endif // _GLIBCXX_INPLACE_VECTOR