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/stl_construct.h>
46#include <bits/stl_uninitialized.h>
47#include <bits/stl_algo.h> // rotate
49namespace std _GLIBCXX_VISIBILITY(default)
51_GLIBCXX_BEGIN_NAMESPACE_VERSION
53 // [indirect], class template indirect
54 template<typename _Tp, size_t _Nm>
60 using value_type = _Tp;
62 using const_pointer = const _Tp*;
63 using reference = value_type&;
64 using const_reference = const value_type&;
65 using size_type = size_t;
66 using difference_type = ptrdiff_t;
68 = __gnu_cxx::__normal_iterator<_Tp*, inplace_vector>;
70 = __gnu_cxx::__normal_iterator<const _Tp*, inplace_vector>;
71 using reverse_iterator = std::reverse_iterator<iterator>;
72 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
74 // [containers.sequences.inplace.vector.cons], construct/copy/destroy
76 inplace_vector() noexcept
80 inplace_vector(size_type __n)
84 std::uninitialized_value_construct_n(data(), __n);
89 inplace_vector(size_type __n, const _Tp& __value)
93 std::uninitialized_fill_n(data(), __n, __value);
97 template<__any_input_iterator _InputIterator>
99 inplace_vector(_InputIterator __first, _InputIterator __last)
102 if (const auto __n = _S_distance(__first, __last))
105 std::uninitialized_copy(__first, __last, data());
110 while (__first != __last)
111 emplace_back(*__first++);
115 template <__detail::__container_compatible_range<_Tp> _Rg>
117 inplace_vector(from_range_t, _Rg&& __rg)
119 { append_range(__rg); }
122 inplace_vector(initializer_list<_Tp> __il)
125 _S_reserve(__il.size());
126 std::uninitialized_copy(__il.begin(), __il.end(), data());
127 _M_size = __il.size();
130 inplace_vector(const inplace_vector&)
131 requires is_trivially_copy_constructible_v<_Tp>
135 inplace_vector(const inplace_vector& __other)
136 noexcept(is_nothrow_copy_constructible_v<_Tp>)
139 std::uninitialized_copy(__other.begin(), __other.end(), data());
140 _M_size = __other.size();
143 inplace_vector(inplace_vector&&)
144 requires is_trivially_move_constructible_v<_Tp>
148 inplace_vector(inplace_vector&& __other)
149 noexcept(is_nothrow_move_constructible_v<_Tp>)
152 std::uninitialized_move(__other.begin(), __other.end(), data());
153 _M_size = __other.size();
157 requires is_trivially_destructible_v<_Tp>
165 operator=(const inplace_vector&)
166 requires is_trivially_copy_assignable_v<_Tp>
167 && is_trivially_copy_constructible_v<_Tp>
168 && is_trivially_destructible_v<_Tp>
171 constexpr inplace_vector&
172 operator=(const inplace_vector& __other)
173 noexcept(is_nothrow_copy_assignable_v<_Tp>
174 && is_nothrow_copy_constructible_v<_Tp>)
176 if (std::addressof(__other) != this) [[likely]]
177 assign(__other.begin(), __other.end());
182 operator=(inplace_vector&&)
183 requires is_trivially_move_assignable_v<_Tp>
184 && is_trivially_move_constructible_v<_Tp>
185 && is_trivially_destructible_v<_Tp>
188 constexpr inplace_vector&
189 operator=(inplace_vector&& __other)
190 noexcept(is_nothrow_move_assignable_v<_Tp>
191 && is_nothrow_move_constructible_v<_Tp>)
193 if (std::addressof(__other) != this) [[likely]]
194 assign(std::make_move_iterator(__other.begin()),
195 std::make_move_iterator(__other.end()));
199 constexpr inplace_vector&
200 operator=(initializer_list<_Tp> __il)
202 assign(__il.begin(), __il.end());
206 template<__any_input_iterator _InputIterator>
208 assign(_InputIterator __first, _InputIterator __last)
210 if (const auto __n = _S_distance(__first, __last))
215 for (size_t __i = 0; __i < _M_size; ++__i, (void)++__first)
216 _M_elems[__i] = *__first;
217 std::uninitialized_copy(__first, __last, end());
220 std::destroy(std::copy(__first, __last, begin()), end());
226 for (;__first != __last && __i < _M_size; ++__first)
227 _M_elems[__i++] = *__first;
228 if (__first == __last)
230 std::_Destroy_n(data() + __i, _M_size - __i);
235 while (__first != __last)
236 emplace_back(*__first++);
241 template<__detail::__container_compatible_range<_Tp> _Rg>
243 assign_range(_Rg&& __rg)
245 if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
247 const auto __sz = ranges::distance(__rg);
252 ranges::copy_n(ranges::begin(__rg), __sz, data());
253 std::destroy(data() + __sz, data() + _M_size);
257 auto [__in, __out] = ranges::copy_n(
258 ranges::begin(__rg), _M_size,
260 ranges::uninitialized_copy(
261 std::move(__in), ranges::end(__rg),
262 __out, unreachable_sentinel);
268 auto __in = ranges::begin(__rg);
269 auto __end = ranges::end(__rg);
271 for (; __n < _M_size && __in != __end; ++__in)
272 _M_elems[__n++] = *__in;
276 std::destroy(data() + __n, data() + _M_size);
282 auto __res = ranges::uninitialized_copy(
283 std::move(__in), __end,
284 data() + __n, data() + _Nm);
285 _M_size = __res.out - data();
286 if (__res.in == ranges::end(__rg))
294 assign(size_type __n, const _Tp& __u)
298 std::uninitialized_fill_n(std::fill_n(data(), _M_size, __u),
301 std::destroy_n(std::fill_n(data(), __n, __u), _M_size - __n);
306 assign(initializer_list<_Tp> __il)
307 { assign(__il.begin(), __il.end()); }
312 begin() noexcept { return iterator(data()); }
315 constexpr const_iterator
316 begin() const noexcept { return const_iterator(data()); }
321 { return iterator(data() + _M_size); }
324 constexpr const_iterator
326 { return const_iterator(data() + _M_size); }
329 constexpr reverse_iterator
331 { return reverse_iterator(end()); }
334 constexpr const_reverse_iterator
335 rbegin() const noexcept
336 { return const_reverse_iterator(end()); }
339 constexpr reverse_iterator
340 rend() noexcept { return reverse_iterator(begin()); }
343 constexpr const_reverse_iterator
344 rend() const noexcept { return const_reverse_iterator(begin()); }
347 constexpr const_iterator
348 cbegin() const noexcept { return begin(); }
351 constexpr const_iterator
352 cend() const noexcept { return end(); }
355 constexpr const_reverse_iterator
356 crbegin() const noexcept { return rbegin(); }
359 constexpr const_reverse_iterator
360 crend() const noexcept { return rend(); }
362 // [containers.sequences.inplace.vector.members] size/capacity
365 empty() const noexcept { return _M_size == 0; }
369 size() const noexcept
372 __builtin_unreachable();
377 static constexpr size_type
378 max_size() noexcept { return _Nm; }
381 static constexpr size_type
382 capacity() noexcept { return _Nm; }
385 resize(size_type __n)
389 std::uninitialized_value_construct_n(data() + _M_size, __n - _M_size);
390 else if (__n < _M_size)
391 std::destroy_n(data() + __n, _M_size - __n);
396 resize(size_type __n, const _Tp& __c)
400 std::uninitialized_fill_n(data() + _M_size, __n - _M_size, __c);
401 else if (__n < _M_size)
402 std::destroy_n(data() + __n, _M_size - __n);
406 static constexpr void
407 reserve(size_type __n)
410 static constexpr void
416 operator[](size_type __n)
418 __glibcxx_requires_subscript(__n);
419 return _M_elems[__n];
423 constexpr const_reference
424 operator[](size_type __n) const
426 __glibcxx_requires_subscript(__n);
427 return _M_elems[__n];
431 constexpr const_reference
432 at(size_type __n) const
435 std::__throw_out_of_range_fmt(__N("inplace_vector::at: __n "
437 ">= size() (which is %zu)"),
439 return _M_elems[__n];
447 std::__throw_out_of_range_fmt(__N("inplace_vector::at: __n "
449 ">= size() (which is %zu)"),
451 return _M_elems[__n];
458 __glibcxx_requires_nonempty();
463 constexpr const_reference
466 __glibcxx_requires_nonempty();
474 __glibcxx_requires_nonempty();
475 return _M_elems[_M_size - 1];
479 constexpr const_reference
482 __glibcxx_requires_nonempty();
483 return _M_elems[_M_size - 1];
486 // [containers.sequences.inplace.vector.data], data access
491 { return static_cast<pointer>(_M_elems); }
495 data() const noexcept
496 { return static_cast<const_pointer>(_M_elems); }
498 // [containers.sequences.inplace.vector.modifiers], modifiers
499 template<typename... _Args>
501 emplace_back(_Args&&... __args)
505 return unchecked_emplace_back(std::forward<_Args>(__args)...);
509 push_back(const _Tp& __x)
510 { return emplace_back(__x); }
514 { return emplace_back(std::move(__x)); }
516 template<__detail::__container_compatible_range<_Tp> _Rg>
518 append_range(_Rg&& __rg)
520 if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
522 const auto __sz = ranges::distance(__rg);
523 if (__sz > (_Nm - size()))
525 // Bounded on output range due PR121143
526 ranges::uninitialized_copy(
527 ranges::begin(__rg), unreachable_sentinel,
528 data() + _M_size, data() + _M_size + __sz);
529 _M_size += size_type(__sz);
533 ranges::subrange<pointer> __tail(data() + _M_size, data() + _Nm);
534 auto [__in, __out] = ranges::uninitialized_copy(__rg, __tail);
535 _M_size = __out - data();
536 if (__in != ranges::end(__rg))
544 __glibcxx_requires_nonempty();
546 _M_elems[_M_size].~_Tp();
549 template<typename... _Args>
551 try_emplace_back(_Args&&... __args)
553 if (_M_size >= _Nm) [[unlikely]]
555 auto& __r = unchecked_emplace_back(std::forward<_Args>(__args)...);
556 return __builtin_addressof(__r);
560 try_push_back(const _Tp& __x)
562 if (_M_size >= _Nm) [[unlikely]]
564 return __builtin_addressof(unchecked_emplace_back(__x));
568 try_push_back(_Tp&& __x)
570 if (_M_size >= _Nm) [[unlikely]]
572 return __builtin_addressof(unchecked_emplace_back(std::move(__x)));
575 template<__detail::__container_compatible_range<_Tp> _Rg>
576 constexpr ranges::borrowed_iterator_t<_Rg>
577 try_append_range(_Rg&& __rg)
579 if constexpr (ranges::sized_range<_Rg>)
581 auto __n = ranges::distance(__rg);
582 if (__n == 0) [[unlikely]]
583 return ranges::begin(__rg);
585 const auto __end = data() + _M_size;
586 const size_t __avail = _Nm - size();
588 _M_size += size_type(__n);
594 return ranges::uninitialized_copy_n(
595 ranges::begin(__rg), __n,
596 __end, unreachable_sentinel).in;
600 ranges::subrange<pointer> __tail(data() + _M_size, data() + _Nm);
601 auto [__in, __out] = ranges::uninitialized_copy(__rg, __tail);
602 _M_size = __out - data();
603 return std::move(__in);
607 template<typename... _Args>
609 unchecked_emplace_back(_Args&&... __args)
611 __glibcxx_assert(_M_size < _Nm);
612 auto __p = std::construct_at(data() + _M_size,
613 std::forward<_Args>(__args)...);
619 unchecked_push_back(const _Tp& __x)
620 { return unchecked_emplace_back(__x); }
623 unchecked_push_back(_Tp&& __x)
624 { return unchecked_emplace_back(std::move(__x)); }
626 template<typename... _Args>
628 emplace(const_iterator __position, _Args&&... __args)
630 size_t __b = __position - cbegin(); // elements before position
631 __glibcxx_assert(__b <= _M_size);
634 iterator __pos = begin() + __b;
635 std::construct_at(data() + _M_size, std::forward<_Args>(__args)...);
637 std::rotate(__pos, end() - 1, end());
642 insert(const_iterator __position, const _Tp& __x)
643 { return emplace(__position, __x); }
646 insert(const_iterator __position, _Tp&& __x)
647 { return emplace(__position, std::move(__x)); }
650 insert(const_iterator __position, size_type __n, const _Tp& __x)
652 size_t __b = __position - cbegin(); // elements before position
653 __glibcxx_assert(__b <= _M_size);
654 if ((_Nm - _M_size) < __n)
656 iterator __pos = begin() + __b;
657 std::uninitialized_fill_n(data() + _M_size, __n, __x);
658 if (std::__exchange(_M_size, _M_size + __n))
659 std::rotate(__pos, end() - __n, end());
663 template<__any_input_iterator _InputIterator>
665 insert(const_iterator __position, _InputIterator __first,
666 _InputIterator __last)
668 size_t __b = __position - cbegin(); // elements before position
669 __glibcxx_assert(__b <= _M_size);
670 iterator __pos = begin() + __b;
671 const size_t __s = _M_size;
672 if (const auto __n = _S_distance(__first, __last))
674 if ((_Nm - _M_size) < __n)
676 std::uninitialized_copy(__first, __last, data() + _M_size);
681 while (__first != __last)
682 emplace_back(*__first++);
685 std::rotate(__pos, begin() + __s, end());
689 template<__detail::__container_compatible_range<_Tp> _Rg>
691 insert_range(const_iterator __position, _Rg&& __rg)
693 iterator __pos = begin() + (__position - cbegin());
694 const auto __end = end();
695 if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
697 const auto __len = ranges::distance(__rg);
698 if (__len > (_Nm - size()))
700 if (!__len) [[unlikely]]
703 const size_type __n = size_type(__len);
704 const size_type __num_after = __end - __pos;
705 if (__num_after >= __n)
707 ranges::uninitialized_move(__end - __n, __end,
708 __end, unreachable_sentinel);
710 ranges::move_backward(__pos, __end - __n, __end);
711 ranges::copy(__rg, __pos);
713 else if constexpr (ranges::forward_range<_Rg>)
715 auto __mid = ranges::next(ranges::begin(__rg), __num_after);
716 ranges::uninitialized_copy(__mid, ranges::end(__rg),
717 __end, unreachable_sentinel);
718 _M_size += __n - __num_after;
719 ranges::uninitialized_move(__pos, __end,
720 __pos + __n, unreachable_sentinel);
721 _M_size += __num_after;
722 ranges::copy(ranges::begin(__rg), __mid, __pos);
726 ranges::uninitialized_copy(
727 ranges::begin(__rg), ranges::end(__rg),
728 __end, unreachable_sentinel);
730 std::rotate(__pos, __end, end());
736 std::rotate(__pos, __end, end());
742 insert(const_iterator __position, initializer_list<_Tp> __il)
743 { return insert(__position, __il.begin(), __il.end()); }
746 erase(const_iterator __position)
748 size_t __n = __position - cbegin();
749 __glibcxx_assert(__n < _M_size);
750 iterator __pos = begin() + __n;
751 std::move(__pos + 1, end(), __pos);
757 erase(const_iterator __first, const_iterator __last)
759 size_t __n = __first - cbegin();
760 size_t __x = __last - __first;
761 __glibcxx_assert(__n <= _M_size);
762 __glibcxx_assert(__x <= _M_size);
763 iterator __pos = begin() + __n;
764 iterator __end = std::move(__pos + __x, end(), __pos);
765 std::destroy_n(__end, __x);
771 swap(inplace_vector& __x)
772 noexcept(is_nothrow_swappable_v<_Tp> && is_nothrow_move_constructible_v<_Tp>)
774 inplace_vector* __vs[2]{ this, std::addressof(__x) };
775 const auto __smaller = __vs[__x.size() < size()];
776 const auto __bigger = __vs[__x.size() >= size()];
777 size_type __n = __smaller->size();
778 size_type __n2 = __bigger->size();
780 if constexpr (is_nothrow_move_constructible_v<_Tp>)
782 for (size_type __i = __n; __i < __n2; ++__i)
784 std::construct_at(__smaller->data() + __i,
785 std::move(*(__bigger->data() + __i)));
786 std::destroy_at(__bigger->data() + __i);
791 std::uninitialized_copy(__bigger->data() + __n,
792 __bigger->data() + __n2,
793 __smaller->data() + __n);
794 std::destroy(__bigger->data() + __n, __bigger->data() + __n2);
796 __smaller->_M_size = __n2;
797 __bigger->_M_size = __n;
800 for (size_type __i = 0; __i < __n; __i++)
801 swap(_M_elems[__i], __x._M_elems[__i]);
807 std::destroy_n(data(), size_t(_M_size));
811 constexpr friend bool
812 operator==(const inplace_vector& __x, const inplace_vector& __y)
813 { return std::equal(__x.begin(), __x.end(), __y.begin(), __y.end()); }
815 constexpr friend auto
816 operator<=>(const inplace_vector& __x, const inplace_vector& __y)
817 requires requires (const _Tp __t) {
818 { __t < __t } -> __detail::__boolean_testable;
821 return std::lexicographical_compare_three_way(__x.begin(), __x.end(),
822 __y.begin(), __y.end(),
823 __detail::__synth3way);
826 constexpr friend void
827 swap(inplace_vector& __x, inplace_vector& __y)
828 noexcept(is_nothrow_swappable_v<_Tp> && is_nothrow_move_constructible_v<_Tp>)
836 // Check whether integer type _UInt is wide enough to store _Nm,
837 // so that we use a smaller type for _M_size when that saves space.
838 template<typename _UInt, bool = (alignof(_Tp) <= sizeof(_UInt))>
839 static constexpr bool __fits
840 = _Nm <= __gnu_cxx::__int_traits<_UInt>::__max;
842 // Don't bother using a smaller type if alignment of the array elements
843 // means that it doesn't actually save space.
844 template<typename _UInt>
845 static constexpr bool __fits<_UInt, false> = false;
847 static consteval auto __select_size_type()
849 if constexpr (__fits<unsigned char>)
850 return (unsigned char)0;
851#if __SHRT_WIDTH__ < __SIZE_WIDTH__
852 else if constexpr (__fits<unsigned short>)
853 return (unsigned short)0;
855#if __INT_WIDTH__ < __SIZE_WIDTH__ && __INT_WIDTH__ > __SHRT_WIDTH__
856 else if constexpr (__fits<unsigned int>)
859#if __LONG_WIDTH__ < __SIZE_WIDTH__ && __LONG_WIDTH__ > __INT_WIDTH__
860 else if constexpr (__fits<unsigned long>)
863 else // Just use size_t.
866 decltype(__select_size_type()) _M_size = 0;
873#if __glibcxx_start_lifetime_as
874 std::start_lifetime_as_array<_Tp>(data(), _Nm);
879 // TODO: use new(_M_elems) _Tp[_Nm]() once PR121068 is fixed
880 if constexpr (is_trivial_v<_Tp>)
881 for (size_t __i = 0; __i < _Nm; ++__i)
882 _M_elems[__i] = _Tp();
884 __builtin_unreachable(); // only trivial types are supported at compile time
888 static constexpr void
889 _S_reserve(size_t __n)
895 template<typename _InputIterator>
896 constexpr static auto
897 _S_distance(_InputIterator __first, _InputIterator __last)
899 if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>
900 || forward_iterator<_InputIterator>)
901 return (size_type)ranges::distance(__first, __last);
902 else if constexpr (derived_from<__iter_category_t<_InputIterator>,
903 forward_iterator_tag>)
904 return (size_type)std::distance(__first, __last);
910 // [inplace.vector.special], specialized algorithms
911 template<typename _Tp, size_t _Nm>
913 swap(inplace_vector<_Tp, _Nm>& __x, inplace_vector<_Tp, _Nm>& __y)
914 noexcept(noexcept(__x.swap(__y)))
917 // specialization for zero capacity, that is required to be trivally copyable
918 // and empty regardless of _Tp.
919 template<typename _Tp>
920 class inplace_vector<_Tp, 0>
924 using value_type = _Tp;
925 using pointer = _Tp*;
926 using const_pointer = const _Tp*;
927 using reference = value_type&;
928 using const_reference = const value_type&;
929 using size_type = size_t;
930 using difference_type = ptrdiff_t;
932 = __gnu_cxx::__normal_iterator<_Tp*, inplace_vector>;
934 = __gnu_cxx::__normal_iterator<const _Tp*, inplace_vector>;
935 using reverse_iterator = std::reverse_iterator<iterator>;
936 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
938 // [containers.sequences.inplace.vector.cons], construct/copy/destroy
939 inplace_vector() = default;
942 inplace_vector(size_type __n)
949 inplace_vector(size_type __n, const _Tp& __value)
955 template<__any_input_iterator _InputIterator>
957 inplace_vector(_InputIterator __first, _InputIterator __last)
959 if (__first != __last)
963 template <__detail::__container_compatible_range<_Tp> _Rg>
965 inplace_vector(from_range_t, _Rg&& __rg)
967 if (ranges::begin(__rg) != ranges::end(__rg))
972 inplace_vector(initializer_list<_Tp> __il)
974 if (__il.size() != 0)
978 inplace_vector(const inplace_vector&) = default;
979 inplace_vector(inplace_vector&&) = default;
982 ~inplace_vector() = default;
985 operator=(const inplace_vector&) = default;
988 operator=(inplace_vector&&) = default;
990 constexpr inplace_vector&
991 operator=(initializer_list<_Tp> __il)
993 if (__il.size() != 0)
997 template<__any_input_iterator _InputIterator>
999 assign(_InputIterator __first, _InputIterator __last)
1001 if (__first != __last)
1002 __throw_bad_alloc();
1005 template<__detail::__container_compatible_range<_Tp> _Rg>
1007 assign_range(_Rg&& __rg)
1009 if (ranges::begin(__rg) != ranges::end(__rg))
1010 __throw_bad_alloc();
1014 assign(size_type __n, const _Tp& __u)
1017 __throw_bad_alloc();
1021 assign(initializer_list<_Tp> __il)
1023 if (__il.size() != 0)
1024 __throw_bad_alloc();
1030 begin() noexcept { return iterator(nullptr); }
1033 constexpr const_iterator
1034 begin() const noexcept { return const_iterator(nullptr); }
1038 end() noexcept { return iterator(nullptr); }
1041 constexpr const_iterator
1042 end() const noexcept { return const_iterator(nullptr); }
1045 constexpr reverse_iterator
1047 { return reverse_iterator(end()); }
1050 constexpr const_reverse_iterator
1051 rbegin() const noexcept
1052 { return const_reverse_iterator(end()); }
1055 constexpr reverse_iterator
1056 rend() noexcept { return reverse_iterator(begin()); }
1059 constexpr const_reverse_iterator
1060 rend() const noexcept { return const_reverse_iterator(begin()); }
1063 constexpr const_iterator
1064 cbegin() const noexcept { return begin(); }
1067 constexpr const_iterator
1068 cend() const noexcept { return end(); }
1071 constexpr const_reverse_iterator
1072 crbegin() const noexcept { return rbegin(); }
1075 constexpr const_reverse_iterator
1076 crend() const noexcept { return rend(); }
1078 // [containers.sequences.inplace.vector.members] size/capacity
1081 empty() const noexcept { return true; }
1085 size() const noexcept { return 0; }
1088 static constexpr size_type
1089 max_size() noexcept { return 0; }
1092 static constexpr size_type
1093 capacity() noexcept { return 0; }
1096 resize(size_type __n)
1099 __throw_bad_alloc();
1103 resize(size_type __n, const _Tp&)
1106 __throw_bad_alloc();
1109 static constexpr void
1110 reserve(size_type __n)
1113 __throw_bad_alloc();
1116 static constexpr void
1120 [[nodiscard,noreturn]]
1122 operator[](size_type)
1123 { __builtin_trap(); }
1125 [[nodiscard,noreturn]]
1126 constexpr const_reference
1127 operator[](size_type) const
1128 { __builtin_trap(); }
1130 [[nodiscard,noreturn]]
1131 constexpr const_reference
1132 at(size_type __n) const
1134 std::__throw_out_of_range_fmt(__N("inplace_vector::at: __n "
1136 ">= size() (which is 0)"),
1140 [[nodiscard,noreturn]]
1144 std::__throw_out_of_range_fmt(__N("inplace_vector::at: __n "
1146 ">= size() (which is 0)"),
1150 [[nodiscard,noreturn]]
1153 { __builtin_trap(); }
1155 [[nodiscard,noreturn]]
1156 constexpr const_reference
1158 { __builtin_trap(); }
1160 [[nodiscard,noreturn]]
1163 { __builtin_trap(); }
1165 [[nodiscard,noreturn]]
1166 constexpr const_reference
1168 { __builtin_trap(); }
1170 // [containers.sequences.inplace.vector.data], data access
1178 constexpr const _Tp*
1179 data() const noexcept
1182 // [containers.sequences.inplace.vector.modifiers], modifiers
1183 template<typename... _Args>
1186 emplace_back(_Args&&...)
1187 { __throw_bad_alloc(); }
1191 push_back(const _Tp&)
1192 { __throw_bad_alloc(); }
1197 { __throw_bad_alloc(); }
1199 template<__detail::__container_compatible_range<_Tp> _Rg>
1201 append_range(_Rg&& __rg)
1203 if (ranges::begin(__rg) != ranges::end(__rg))
1204 __throw_bad_alloc();
1210 { __builtin_trap(); }
1212 template<typename... _Args>
1214 try_emplace_back(_Args&&...)
1218 try_push_back(const _Tp&)
1222 try_push_back(_Tp&&)
1225 template<__detail::__container_compatible_range<_Tp> _Rg>
1226 constexpr ranges::borrowed_iterator_t<_Rg>
1227 try_append_range(_Rg&& __rg)
1228 { return ranges::begin(__rg); }
1230 template<typename... _Args>
1233 unchecked_emplace_back(_Args&&...)
1234 { __builtin_trap(); }
1238 unchecked_push_back(const _Tp&)
1239 { __builtin_trap(); }
1243 unchecked_push_back(_Tp&&)
1244 { __builtin_trap(); }
1246 template<typename... _Args>
1249 emplace(const_iterator, _Args&&...)
1250 { __throw_bad_alloc(); }
1254 insert(const_iterator, const _Tp&)
1255 { __throw_bad_alloc(); }
1259 insert(const_iterator, _Tp&&)
1260 { __throw_bad_alloc(); }
1263 insert(const_iterator, size_type __n, const _Tp&)
1266 __throw_bad_alloc();
1270 template<typename _InputIterator>
1272 insert(const_iterator, _InputIterator __first, _InputIterator __last)
1274 if (__first != __last)
1275 __throw_bad_alloc();
1279 template<__detail::__container_compatible_range<_Tp> _Rg>
1281 insert_range(const_iterator, _Rg&& __rg)
1283 if (ranges::begin(__rg) != ranges::end(__rg))
1284 __throw_bad_alloc();
1289 insert(const_iterator, initializer_list<_Tp> __il)
1291 if (__il.size() != 0)
1292 __throw_bad_alloc();
1298 erase(const_iterator)
1299 { __builtin_trap(); }
1302 erase(const_iterator __first, const_iterator __last)
1304 __glibcxx_assert(__first == __last);
1309 swap(inplace_vector& __x)
1317 constexpr friend bool
1318 operator==(const inplace_vector&, const inplace_vector&)
1321 constexpr friend auto
1322 operator<=>(const inplace_vector&, const inplace_vector&)
1323 requires requires (const _Tp __t) {
1324 { __t < __t } -> __detail::__boolean_testable;
1326 { return std::strong_ordering::equal; }
1328 // n.b. there is not explicit wording requiring that swap for inplace_vector,
1329 // with zero size, works even if element type is not swappable. However given
1330 // that move operations are required to be present and trivial, it makes sense
1332 constexpr friend void
1333 swap(inplace_vector&, inplace_vector&) noexcept
1337 template<typename _Tp, size_t _Nm, typename _Predicate>
1339 erase_if(inplace_vector<_Tp, _Nm>& __cont, _Predicate __pred)
1341 using namespace __gnu_cxx;
1342 const auto __osz = __cont.size();
1343 const auto __end = __cont.end();
1344 auto __removed = std::__remove_if(__cont.begin(), __end,
1346 if (__removed != __end)
1348 __cont.erase(__niter_wrap(__cont.begin(), __removed),
1350 return __osz - __cont.size();
1356 template<typename _Tp, size_t _Nm, typename _Up = _Tp>
1358 erase(inplace_vector<_Tp, _Nm>& __cont, const _Up& __value)
1359 { return std::erase_if(__cont, __gnu_cxx::__ops::__equal_to(__value)); }
1361_GLIBCXX_END_NAMESPACE_VERSION
1364#endif // __glibcxx_inplace_vector
1365#endif // _GLIBCXX_INPLACE_VECTOR