libstdc++
inplace_vector
Go to the documentation of this file.
1// Sequence container with fixed capacity -*- C++ -*-
2
3// Copyright The GNU Toolchain Authors.
4//
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)
9// any later version.
10
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.
15
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.
19
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/>.
24
25/** @file include/inplace_vector
26 * This is a Standard C++ Library header.
27 * @ingroup sequences
28 */
29
30#ifndef _GLIBCXX_INPLACE_VECTOR
31#define _GLIBCXX_INPLACE_VECTOR 1
32
33#pragma GCC system_header
34
35#define __glibcxx_want_inplace_vector
36#include <bits/version.h>
37
38#ifdef __glibcxx_inplace_vector // C++ >= 26
39#include <compare>
40#include <initializer_list>
42#include <bits/range_access.h>
43#include <bits/ranges_base.h> // borrowed_iterator_t, __detail::__container_compatible_range
44#include <bits/ranges_util.h> // subrange
46#include <bits/stl_construct.h>
48#include <bits/stl_algo.h> // rotate
49
50namespace std _GLIBCXX_VISIBILITY(default)
51{
52_GLIBCXX_BEGIN_NAMESPACE_VERSION
53_GLIBCXX_BEGIN_NAMESPACE_CONTAINER
54
55 // [indirect], class template indirect
56 template<typename _Tp, size_t _Nm>
57 class inplace_vector
58 {
59 public:
60
61 // types:
62 using value_type = _Tp;
63 using pointer = _Tp*;
64 using const_pointer = const _Tp*;
65 using reference = value_type&;
66 using const_reference = const value_type&;
67 using size_type = size_t;
68 using difference_type = ptrdiff_t;
69 using iterator
70 = __gnu_cxx::__normal_iterator<_Tp*, inplace_vector>;
71 using const_iterator
72 = __gnu_cxx::__normal_iterator<const _Tp*, inplace_vector>;
73 using reverse_iterator = std::reverse_iterator<iterator>;
74 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
75
76 // [containers.sequences.inplace.vector.cons], construct/copy/destroy
77 constexpr
78 inplace_vector() noexcept
79 { _M_init(); }
80
81 constexpr explicit
82 inplace_vector(size_type __n)
83 {
84 _M_init();
85 _S_reserve(__n);
87 _M_size = __n;
88 }
89
90 constexpr
91 inplace_vector(size_type __n, const _Tp& __value)
92 {
93 _M_init();
94 _S_reserve(__n);
95 std::uninitialized_fill_n(data(), __n, __value);
96 _M_size = __n;
97 }
98
99 template<__any_input_iterator _InputIterator>
100 constexpr
101 inplace_vector(_InputIterator __first, _InputIterator __last)
102 : inplace_vector()
103 {
104 if (const auto __n = _S_distance(__first, __last))
105 {
106 _S_reserve(__n);
107 std::uninitialized_copy(__first, __last, data());
108 _M_size = __n;
109 }
110 else
111 {
112 while (__first != __last)
113 emplace_back(*__first++);
114 }
115 }
116
117 template <__detail::__container_compatible_range<_Tp> _Rg>
118 constexpr
119 inplace_vector(from_range_t, _Rg&& __rg)
120 : inplace_vector()
121 { append_range(__rg); }
122
123 constexpr
124 inplace_vector(initializer_list<_Tp> __il)
125 {
126 _M_init();
127 _S_reserve(__il.size());
128 std::uninitialized_copy(__il.begin(), __il.end(), data());
129 _M_size = __il.size();
130 }
131
132 inplace_vector(const inplace_vector&)
133 requires is_trivially_copy_constructible_v<_Tp>
134 = default;
135
136 constexpr
137 inplace_vector(const inplace_vector& __other)
138 noexcept(is_nothrow_copy_constructible_v<_Tp>)
139 {
140 _M_init();
141 std::uninitialized_copy(__other.begin(), __other.end(), data());
142 _M_size = __other.size();
143 }
144
145 inplace_vector(inplace_vector&&)
146 requires is_trivially_move_constructible_v<_Tp>
147 = default;
148
149 constexpr
150 inplace_vector(inplace_vector&& __other)
151 noexcept(is_nothrow_move_constructible_v<_Tp>)
152 {
153 _M_init();
154 std::uninitialized_move(__other.begin(), __other.end(), data());
155 _M_size = __other.size();
156 }
157
158 ~inplace_vector()
159 requires is_trivially_destructible_v<_Tp>
160 = default;
161
162 constexpr
163 ~inplace_vector()
164 { clear(); }
165
166 inplace_vector&
167 operator=(const inplace_vector&)
168 requires is_trivially_copy_assignable_v<_Tp>
169 && is_trivially_copy_constructible_v<_Tp>
170 && is_trivially_destructible_v<_Tp>
171 = default;
172
173 constexpr inplace_vector&
174 operator=(const inplace_vector& __other)
175 noexcept(is_nothrow_copy_assignable_v<_Tp>
176 && is_nothrow_copy_constructible_v<_Tp>)
177 {
178 if (std::addressof(__other) != this) [[likely]]
179 assign(__other.begin(), __other.end());
180 return *this;
181 }
182
183 inplace_vector&
184 operator=(inplace_vector&&)
185 requires is_trivially_move_assignable_v<_Tp>
186 && is_trivially_move_constructible_v<_Tp>
187 && is_trivially_destructible_v<_Tp>
188 = default;
189
190 constexpr inplace_vector&
191 operator=(inplace_vector&& __other)
192 noexcept(is_nothrow_move_assignable_v<_Tp>
193 && is_nothrow_move_constructible_v<_Tp>)
194 {
195 if (std::addressof(__other) != this) [[likely]]
196 assign(std::make_move_iterator(__other.begin()),
197 std::make_move_iterator(__other.end()));
198 return *this;
199 }
200
201 constexpr inplace_vector&
202 operator=(initializer_list<_Tp> __il)
203 {
204 assign(__il.begin(), __il.end());
205 return *this;
206 }
207
208 template<__any_input_iterator _InputIterator>
209 constexpr void
210 assign(_InputIterator __first, _InputIterator __last)
211 {
212 if (const auto __n = _S_distance(__first, __last))
213 {
214 _S_reserve(__n);
215 if (_M_size <= __n)
216 {
217 for (size_t __i = 0; __i < _M_size; ++__i, (void)++__first)
218 _M_elems[__i] = *__first;
219 std::uninitialized_copy(__first, __last, end());
220 }
221 else
222 std::destroy(std::copy(__first, __last, begin()), end());
223 _M_size = __n;
224 }
225 else
226 {
227 size_t __i = 0;
228 for (;__first != __last && __i < _M_size; ++__first)
229 _M_elems[__i++] = *__first;
230 if (__first == __last)
231 {
232 std::_Destroy_n(data() + __i, _M_size - __i);
233 _M_size = __i;
234 }
235 else
236 {
237 while (__first != __last)
238 emplace_back(*__first++);
239 }
240 }
241 }
242
243 template<__detail::__container_compatible_range<_Tp> _Rg>
244 constexpr void
245 assign_range(_Rg&& __rg)
246 {
247 if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
248 {
249 const auto __sz = ranges::distance(__rg);
250 if (__sz > _Nm)
251 __throw_bad_alloc();
252 if (__sz <= size())
253 {
254 ranges::copy_n(ranges::begin(__rg), __sz, data());
255 std::destroy(data() + __sz, data() + _M_size);
256 }
257 else
258 {
259 auto [__in, __out] = ranges::copy_n(
260 ranges::begin(__rg), _M_size,
261 data());
262 ranges::uninitialized_copy(
263 std::move(__in), ranges::end(__rg),
264 __out, unreachable_sentinel);
265 }
266 _M_size = __sz;
267 }
268 else
269 {
270 auto __in = ranges::begin(__rg);
271 auto __end = ranges::end(__rg);
272 size_type __n = 0;
273 for (; __n < _M_size && __in != __end; ++__in)
274 _M_elems[__n++] = *__in;
275
276 if (__in == __end)
277 {
278 std::destroy(data() + __n, data() + _M_size);
279 _M_size = __n;
280 return;
281 }
282 else if (__n < _Nm)
283 {
284 auto __res = ranges::uninitialized_copy(
285 std::move(__in), __end,
286 data() + __n, data() + _Nm);
287 _M_size = __res.out - data();
288 if (__res.in == ranges::end(__rg))
289 return;
290 }
291 __throw_bad_alloc();
292 }
293 }
294
295 constexpr void
296 assign(size_type __n, const _Tp& __u)
297 {
298 _S_reserve(__n);
299 if (_M_size <= __n)
300 std::uninitialized_fill_n(std::fill_n(data(), _M_size, __u),
301 __n - _M_size, __u);
302 else
303 std::destroy_n(std::fill_n(data(), __n, __u), _M_size - __n);
304 _M_size = __n;
305 }
306
307 constexpr void
308 assign(initializer_list<_Tp> __il)
309 { assign(__il.begin(), __il.end()); }
310
311 // iterators
312 [[nodiscard]]
313 constexpr iterator
314 begin() noexcept { return iterator(data()); }
315
316 [[nodiscard]]
317 constexpr const_iterator
318 begin() const noexcept { return const_iterator(data()); }
319
320 [[nodiscard]]
321 constexpr iterator
322 end() noexcept
323 { return iterator(data() + _M_size); }
324
325 [[nodiscard]]
326 constexpr const_iterator
327 end() const noexcept
328 { return const_iterator(data() + _M_size); }
329
330 [[nodiscard]]
331 constexpr reverse_iterator
332 rbegin() noexcept
333 { return reverse_iterator(end()); }
334
335 [[nodiscard]]
336 constexpr const_reverse_iterator
337 rbegin() const noexcept
338 { return const_reverse_iterator(end()); }
339
340 [[nodiscard]]
341 constexpr reverse_iterator
342 rend() noexcept { return reverse_iterator(begin()); }
343
344 [[nodiscard]]
345 constexpr const_reverse_iterator
346 rend() const noexcept { return const_reverse_iterator(begin()); }
347
348 [[nodiscard]]
349 constexpr const_iterator
350 cbegin() const noexcept { return begin(); }
351
352 [[nodiscard]]
353 constexpr const_iterator
354 cend() const noexcept { return end(); }
355
356 [[nodiscard]]
357 constexpr const_reverse_iterator
358 crbegin() const noexcept { return rbegin(); }
359
360 [[nodiscard]]
361 constexpr const_reverse_iterator
362 crend() const noexcept { return rend(); }
363
364 // [containers.sequences.inplace.vector.members] size/capacity
365 [[nodiscard]]
366 constexpr bool
367 empty() const noexcept { return _M_size == 0; }
368
369 [[nodiscard]]
370 constexpr size_type
371 size() const noexcept
372 {
373 if (_M_size > _Nm)
374 __builtin_unreachable();
375 return _M_size;
376 }
377
378 [[nodiscard]]
379 static constexpr size_type
380 max_size() noexcept { return _Nm; }
381
382 [[nodiscard]]
383 static constexpr size_type
384 capacity() noexcept { return _Nm; }
385
386 constexpr void
387 resize(size_type __n)
388 {
389 _S_reserve(__n);
390 if (__n > _M_size)
391 std::uninitialized_value_construct_n(data() + _M_size, __n - _M_size);
392 else if (__n < _M_size)
393 std::destroy_n(data() + __n, _M_size - __n);
394 _M_size = __n;
395 }
396
397 constexpr void
398 resize(size_type __n, const _Tp& __c)
399 {
400 _S_reserve(__n);
401 if (__n > _M_size)
402 std::uninitialized_fill_n(data() + _M_size, __n - _M_size, __c);
403 else if (__n < _M_size)
404 std::destroy_n(data() + __n, _M_size - __n);
405 _M_size = __n;
406 }
407
408 static constexpr void
409 reserve(size_type __n)
410 { _S_reserve(__n); }
411
412 static constexpr void
413 shrink_to_fit() { }
414
415 // element access
416 [[nodiscard]]
417 constexpr reference
418 operator[](size_type __n)
419 {
420 __glibcxx_requires_subscript(__n);
421 return _M_elems[__n];
422 }
423
424 [[nodiscard]]
425 constexpr const_reference
426 operator[](size_type __n) const
427 {
428 __glibcxx_requires_subscript(__n);
429 return _M_elems[__n];
430 }
431
432 [[nodiscard]]
433 constexpr const_reference
434 at(size_type __n) const
435 {
436 if (__n >= _M_size)
437 std::__throw_out_of_range_fmt(__N("inplace_vector::at: __n "
438 "(which is %zu) "
439 ">= size() (which is %zu)"),
440 __n, _M_size);
441 return _M_elems[__n];
442 }
443
444 [[nodiscard]]
445 constexpr reference
446 at(size_type __n)
447 {
448 if (__n >= _M_size)
449 std::__throw_out_of_range_fmt(__N("inplace_vector::at: __n "
450 "(which is %zu) "
451 ">= size() (which is %zu)"),
452 __n, _M_size);
453 return _M_elems[__n];
454 }
455
456 [[nodiscard]]
457 constexpr reference
458 front()
459 {
460 __glibcxx_requires_nonempty();
461 return _M_elems[0];
462 }
463
464 [[nodiscard]]
465 constexpr const_reference
466 front() const
467 {
468 __glibcxx_requires_nonempty();
469 return _M_elems[0];
470 }
471
472 [[nodiscard]]
473 constexpr reference
474 back()
475 {
476 __glibcxx_requires_nonempty();
477 return _M_elems[_M_size - 1];
478 }
479
480 [[nodiscard]]
481 constexpr const_reference
482 back() const
483 {
484 __glibcxx_requires_nonempty();
485 return _M_elems[_M_size - 1];
486 }
487
488 // [containers.sequences.inplace.vector.data], data access
489
490 [[nodiscard]]
491 constexpr _Tp*
492 data() noexcept
493 { return static_cast<pointer>(_M_elems); }
494
495 [[nodiscard]]
496 constexpr const _Tp*
497 data() const noexcept
498 { return static_cast<const_pointer>(_M_elems); }
499
500 // [containers.sequences.inplace.vector.modifiers], modifiers
501 template<typename... _Args>
502 constexpr _Tp&
503 emplace_back(_Args&&... __args)
504 {
505 if (_M_size >= _Nm)
506 __throw_bad_alloc();
507 return unchecked_emplace_back(std::forward<_Args>(__args)...);
508 }
509
510 constexpr _Tp&
511 push_back(const _Tp& __x)
512 { return emplace_back(__x); }
513
514 constexpr _Tp&
515 push_back(_Tp&& __x)
516 { return emplace_back(std::move(__x)); }
517
518 template<__detail::__container_compatible_range<_Tp> _Rg>
519 constexpr void
520 append_range(_Rg&& __rg)
521 {
522 if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
523 {
524 const auto __sz = ranges::distance(__rg);
525 if (__sz > (_Nm - size()))
526 __throw_bad_alloc();
527 // Bounded on output range due PR121143
528 ranges::uninitialized_copy(
529 ranges::begin(__rg), unreachable_sentinel,
530 data() + _M_size, data() + _M_size + __sz);
531 _M_size += size_type(__sz);
532 }
533 else
534 {
535 ranges::subrange<pointer> __tail(data() + _M_size, data() + _Nm);
536 auto [__in, __out] = ranges::uninitialized_copy(__rg, __tail);
537 _M_size = __out - data();
538 if (__in != ranges::end(__rg))
539 __throw_bad_alloc();
540 }
541 }
542
543 constexpr void
544 pop_back()
545 {
546 __glibcxx_requires_nonempty();
547 --_M_size;
548 _M_elems[_M_size].~_Tp();
549 }
550
551 template<typename... _Args>
552 constexpr _Tp*
553 try_emplace_back(_Args&&... __args)
554 {
555 if (_M_size >= _Nm) [[unlikely]]
556 return nullptr;
557 auto& __r = unchecked_emplace_back(std::forward<_Args>(__args)...);
558 return __builtin_addressof(__r);
559 }
560
561 constexpr _Tp*
562 try_push_back(const _Tp& __x)
563 {
564 if (_M_size >= _Nm) [[unlikely]]
565 return nullptr;
566 return __builtin_addressof(unchecked_emplace_back(__x));
567 }
568
569 constexpr _Tp*
570 try_push_back(_Tp&& __x)
571 {
572 if (_M_size >= _Nm) [[unlikely]]
573 return nullptr;
574 return __builtin_addressof(unchecked_emplace_back(std::move(__x)));
575 }
576
577 template<__detail::__container_compatible_range<_Tp> _Rg>
578 constexpr ranges::borrowed_iterator_t<_Rg>
579 try_append_range(_Rg&& __rg)
580 {
581 if constexpr (ranges::sized_range<_Rg>)
582 {
583 auto __n = ranges::distance(__rg);
584 if (__n == 0) [[unlikely]]
585 return ranges::begin(__rg);
586
587 const auto __end = data() + _M_size;
588 const size_t __avail = _Nm - size();
589 if (__n <= __avail)
590 _M_size += size_type(__n);
591 else
592 {
593 __n = __avail;
594 _M_size = _Nm;
595 }
596 return ranges::uninitialized_copy_n(
597 ranges::begin(__rg), __n,
598 __end, unreachable_sentinel).in;
599 }
600 else
601 {
602 ranges::subrange<pointer> __tail(data() + _M_size, data() + _Nm);
603 auto [__in, __out] = ranges::uninitialized_copy(__rg, __tail);
604 _M_size = __out - data();
605 return std::move(__in);
606 }
607 }
608
609 template<typename... _Args>
610 constexpr _Tp&
611 unchecked_emplace_back(_Args&&... __args)
612 {
613 __glibcxx_assert(_M_size < _Nm);
614 auto __p = std::construct_at(data() + _M_size,
615 std::forward<_Args>(__args)...);
616 ++_M_size;
617 return *__p;
618 }
619
620 constexpr _Tp&
621 unchecked_push_back(const _Tp& __x)
622 { return unchecked_emplace_back(__x); }
623
624 constexpr _Tp&
625 unchecked_push_back(_Tp&& __x)
626 { return unchecked_emplace_back(std::move(__x)); }
627
628 template<typename... _Args>
629 constexpr iterator
630 emplace(const_iterator __position, _Args&&... __args)
631 {
632 size_t __b = __position - cbegin(); // elements before position
633 __glibcxx_assert(__b <= _M_size);
634 if (_M_size >= _Nm)
635 __throw_bad_alloc();
636 iterator __pos = begin() + __b;
637 std::construct_at(data() + _M_size, std::forward<_Args>(__args)...);
638 if (_M_size++)
639 std::rotate(__pos, end() - 1, end());
640 return __pos;
641 }
642
643 constexpr iterator
644 insert(const_iterator __position, const _Tp& __x)
645 { return emplace(__position, __x); }
646
647 constexpr iterator
648 insert(const_iterator __position, _Tp&& __x)
649 { return emplace(__position, std::move(__x)); }
650
651 constexpr iterator
652 insert(const_iterator __position, size_type __n, const _Tp& __x)
653 {
654 size_t __b = __position - cbegin(); // elements before position
655 __glibcxx_assert(__b <= _M_size);
656 if ((_Nm - _M_size) < __n)
657 __throw_bad_alloc();
658 iterator __pos = begin() + __b;
659 std::uninitialized_fill_n(data() + _M_size, __n, __x);
660 if (std::__exchange(_M_size, _M_size + __n))
661 std::rotate(__pos, end() - __n, end());
662 return __pos;
663 }
664
665 template<__any_input_iterator _InputIterator>
666 constexpr iterator
667 insert(const_iterator __position, _InputIterator __first,
668 _InputIterator __last)
669 {
670 size_t __b = __position - cbegin(); // elements before position
671 __glibcxx_assert(__b <= _M_size);
672 iterator __pos = begin() + __b;
673 const size_t __s = _M_size;
674 if (const auto __n = _S_distance(__first, __last))
675 {
676 if ((_Nm - _M_size) < __n)
677 __throw_bad_alloc();
678 std::uninitialized_copy(__first, __last, data() + _M_size);
679 _M_size += __n;
680 }
681 else
682 {
683 while (__first != __last)
684 emplace_back(*__first++);
685 }
686 if (__s)
687 std::rotate(__pos, begin() + __s, end());
688 return __pos;
689 }
690
691 template<__detail::__container_compatible_range<_Tp> _Rg>
692 constexpr iterator
693 insert_range(const_iterator __position, _Rg&& __rg)
694 {
695 iterator __pos = begin() + (__position - cbegin());
696 const auto __end = end();
697 if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
698 {
699 const auto __len = ranges::distance(__rg);
700 if (__len > (_Nm - size()))
701 __throw_bad_alloc();
702 if (!__len) [[unlikely]]
703 return __pos;
704
705 const size_type __n = size_type(__len);
706 const size_type __num_after = __end - __pos;
707 if (__num_after >= __n)
708 {
709 ranges::uninitialized_move(__end - __n, __end,
710 __end, unreachable_sentinel);
711 _M_size += __n;
712 ranges::move_backward(__pos, __end - __n, __end);
713 ranges::copy(__rg, __pos);
714 }
715 else if constexpr (ranges::forward_range<_Rg>)
716 {
717 auto __mid = ranges::next(ranges::begin(__rg), __num_after);
718 ranges::uninitialized_copy(__mid, ranges::end(__rg),
719 __end, unreachable_sentinel);
720 _M_size += __n - __num_after;
721 ranges::uninitialized_move(__pos, __end,
722 __pos + __n, unreachable_sentinel);
723 _M_size += __num_after;
724 ranges::copy(ranges::begin(__rg), __mid, __pos);
725 }
726 else
727 {
728 ranges::uninitialized_copy(
729 ranges::begin(__rg), ranges::end(__rg),
730 __end, unreachable_sentinel);
731 _M_size += __n;
732 std::rotate(__pos, __end, end());
733 }
734 }
735 else
736 {
737 append_range(__rg);
738 std::rotate(__pos, __end, end());
739 }
740 return __pos;
741 }
742
743 constexpr iterator
744 insert(const_iterator __position, initializer_list<_Tp> __il)
745 { return insert(__position, __il.begin(), __il.end()); }
746
747 constexpr iterator
748 erase(const_iterator __position)
749 {
750 size_t __n = __position - cbegin();
751 __glibcxx_assert(__n < _M_size);
752 iterator __pos = begin() + __n;
753 std::move(__pos + 1, end(), __pos);
754 pop_back();
755 return __pos;
756 }
757
758 constexpr iterator
759 erase(const_iterator __first, const_iterator __last)
760 {
761 size_t __n = __first - cbegin();
762 size_t __x = __last - __first;
763 __glibcxx_assert(__n <= _M_size);
764 __glibcxx_assert(__x <= _M_size);
765 iterator __pos = begin() + __n;
766 iterator __end = std::move(__pos + __x, end(), __pos);
767 std::destroy_n(__end, __x);
768 _M_size -= __x;
769 return __pos;
770 }
771
772 constexpr void
773 swap(inplace_vector& __x)
774 noexcept(is_nothrow_swappable_v<_Tp> && is_nothrow_move_constructible_v<_Tp>)
775 {
776 inplace_vector* __vs[2]{ this, std::addressof(__x) };
777 const auto __smaller = __vs[__x.size() < size()];
778 const auto __bigger = __vs[__x.size() >= size()];
779 size_type __n = __smaller->size();
780 size_type __n2 = __bigger->size();
781
782 if constexpr (is_nothrow_move_constructible_v<_Tp>)
783 {
784 for (size_type __i = __n; __i < __n2; ++__i)
785 {
786 std::construct_at(__smaller->data() + __i,
787 std::move(*(__bigger->data() + __i)));
788 std::destroy_at(__bigger->data() + __i);
789 }
790 }
791 else
792 {
793 std::uninitialized_copy(__bigger->data() + __n,
794 __bigger->data() + __n2,
795 __smaller->data() + __n);
796 std::destroy(__bigger->data() + __n, __bigger->data() + __n2);
797 }
798 __smaller->_M_size = __n2;
799 __bigger->_M_size = __n;
800
801 using std::swap;
802 for (size_type __i = 0; __i < __n; __i++)
803 swap(_M_elems[__i], __x._M_elems[__i]);
804 }
805
806 constexpr void
807 clear() noexcept
808 {
809 std::destroy_n(data(), size_t(_M_size));
810 _M_size = 0;
811 }
812
813 constexpr friend bool
814 operator==(const inplace_vector& __x, const inplace_vector& __y)
815 { return std::equal(__x.begin(), __x.end(), __y.begin(), __y.end()); }
816
817 constexpr friend auto
818 operator<=>(const inplace_vector& __x, const inplace_vector& __y)
819 requires requires (const _Tp __t) {
820 { __t < __t } -> __detail::__boolean_testable;
821 }
822 {
823 return std::lexicographical_compare_three_way(__x.begin(), __x.end(),
824 __y.begin(), __y.end(),
825 __detail::__synth3way);
826 }
827
828 // [inplace.vector.special], specialized algorithms
829 constexpr friend void
830 swap(inplace_vector& __x, inplace_vector& __y)
831 noexcept(is_nothrow_swappable_v<_Tp> && is_nothrow_move_constructible_v<_Tp>)
832 { __x.swap(__y); }
833
834 private:
835 union {
836 _Tp _M_elems[_Nm];
837 };
838
839 // Check whether integer type _UInt is wide enough to store _Nm,
840 // so that we use a smaller type for _M_size when that saves space.
841 template<typename _UInt, bool = (alignof(_Tp) <= sizeof(_UInt))>
842 static constexpr bool __fits
843 = _Nm <= __gnu_cxx::__int_traits<_UInt>::__max;
844
845 // Don't bother using a smaller type if alignment of the array elements
846 // means that it doesn't actually save space.
847 template<typename _UInt>
848 static constexpr bool __fits<_UInt, false> = false;
849
850 static consteval auto __select_size_type()
851 {
852 if constexpr (__fits<unsigned char>)
853 return (unsigned char)0;
854#if __SHRT_WIDTH__ < __SIZE_WIDTH__
855 else if constexpr (__fits<unsigned short>)
856 return (unsigned short)0;
857#endif
858#if __INT_WIDTH__ < __SIZE_WIDTH__ && __INT_WIDTH__ > __SHRT_WIDTH__
859 else if constexpr (__fits<unsigned int>)
860 return 0u;
861#endif
862#if __LONG_WIDTH__ < __SIZE_WIDTH__ && __LONG_WIDTH__ > __INT_WIDTH__
863 else if constexpr (__fits<unsigned long>)
864 return 0ul;
865#endif
866 else // Just use size_t.
867 return 0uz;
868 }
869 decltype(__select_size_type()) _M_size = 0;
870
871 constexpr void
872 _M_init()
873 {
874 if !consteval
875 {
876#if __glibcxx_start_lifetime_as
877 std::start_lifetime_as_array<_Tp>(data(), _Nm);
878#endif
879 }
880 else
881 {
882 // TODO: use new(_M_elems) _Tp[_Nm]() once PR121068 is fixed
883 if constexpr (is_trivial_v<_Tp>)
884 for (size_t __i = 0; __i < _Nm; ++__i)
885 _M_elems[__i] = _Tp();
886 else
887 __builtin_unreachable(); // only trivial types are supported at compile time
888 }
889 }
890
891 static constexpr void
892 _S_reserve(size_t __n)
893 {
894 if (__n > _Nm)
895 __throw_bad_alloc();
896 }
897
898 template<typename _InputIterator>
899 constexpr static auto
900 _S_distance(_InputIterator __first, _InputIterator __last)
901 {
902 if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>
903 || forward_iterator<_InputIterator>)
904 return (size_type)ranges::distance(__first, __last);
905 else if constexpr (derived_from<__iter_category_t<_InputIterator>,
906 forward_iterator_tag>)
907 return (size_type)std::distance(__first, __last);
908 else
909 return false_type{};
910 }
911 };
912
913 // specialization for zero capacity, that is required to be trivally copyable
914 // and empty regardless of _Tp.
915 template<typename _Tp>
916 class inplace_vector<_Tp, 0>
917 {
918 public:
919 // types:
920 using value_type = _Tp;
921 using pointer = _Tp*;
922 using const_pointer = const _Tp*;
923 using reference = value_type&;
924 using const_reference = const value_type&;
925 using size_type = size_t;
926 using difference_type = ptrdiff_t;
927 using iterator
928 = __gnu_cxx::__normal_iterator<_Tp*, inplace_vector>;
929 using const_iterator
930 = __gnu_cxx::__normal_iterator<const _Tp*, inplace_vector>;
931 using reverse_iterator = std::reverse_iterator<iterator>;
932 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
933
934 // [containers.sequences.inplace.vector.cons], construct/copy/destroy
935 inplace_vector() = default;
936
937 constexpr explicit
938 inplace_vector(size_type __n)
939 {
940 if (__n != 0)
941 __throw_bad_alloc();
942 }
943
944 constexpr
945 inplace_vector(size_type __n, const _Tp& __value)
946 {
947 if (__n != 0)
948 __throw_bad_alloc();
949 }
950
951 template<__any_input_iterator _InputIterator>
952 constexpr
953 inplace_vector(_InputIterator __first, _InputIterator __last)
954 {
955 if (__first != __last)
956 __throw_bad_alloc();
957 }
958
959 template <__detail::__container_compatible_range<_Tp> _Rg>
960 constexpr
961 inplace_vector(from_range_t, _Rg&& __rg)
962 {
963 if (ranges::begin(__rg) != ranges::end(__rg))
964 __throw_bad_alloc();
965 }
966
967 constexpr
968 inplace_vector(initializer_list<_Tp> __il)
969 {
970 if (__il.size() != 0)
971 __throw_bad_alloc();
972 }
973
974 inplace_vector(const inplace_vector&) = default;
975 inplace_vector(inplace_vector&&) = default;
976
977 constexpr
978 ~inplace_vector() = default;
979
980 inplace_vector&
981 operator=(const inplace_vector&) = default;
982
983 inplace_vector&
984 operator=(inplace_vector&&) = default;
985
986 constexpr inplace_vector&
987 operator=(initializer_list<_Tp> __il)
988 {
989 if (__il.size() != 0)
990 __throw_bad_alloc();
991 return *this;
992 }
993
994 template<__any_input_iterator _InputIterator>
995 constexpr void
996 assign(_InputIterator __first, _InputIterator __last)
997 {
998 if (__first != __last)
999 __throw_bad_alloc();
1000 }
1001
1002 template<__detail::__container_compatible_range<_Tp> _Rg>
1003 constexpr void
1004 assign_range(_Rg&& __rg)
1005 {
1006 if (ranges::begin(__rg) != ranges::end(__rg))
1007 __throw_bad_alloc();
1008 }
1009
1010 constexpr void
1011 assign(size_type __n, const _Tp& __u)
1012 {
1013 if (__n != 0)
1014 __throw_bad_alloc();
1015 }
1016
1017 constexpr void
1018 assign(initializer_list<_Tp> __il)
1019 {
1020 if (__il.size() != 0)
1021 __throw_bad_alloc();
1022 }
1023
1024 // iterators
1025 [[nodiscard]]
1026 constexpr iterator
1027 begin() noexcept { return iterator(nullptr); }
1028
1029 [[nodiscard]]
1030 constexpr const_iterator
1031 begin() const noexcept { return const_iterator(nullptr); }
1032
1033 [[nodiscard]]
1034 constexpr iterator
1035 end() noexcept { return iterator(nullptr); }
1036
1037 [[nodiscard]]
1038 constexpr const_iterator
1039 end() const noexcept { return const_iterator(nullptr); }
1040
1041 [[nodiscard]]
1042 constexpr reverse_iterator
1043 rbegin() noexcept
1044 { return reverse_iterator(end()); }
1045
1046 [[nodiscard]]
1047 constexpr const_reverse_iterator
1048 rbegin() const noexcept
1049 { return const_reverse_iterator(end()); }
1050
1051 [[nodiscard]]
1052 constexpr reverse_iterator
1053 rend() noexcept { return reverse_iterator(begin()); }
1054
1055 [[nodiscard]]
1056 constexpr const_reverse_iterator
1057 rend() const noexcept { return const_reverse_iterator(begin()); }
1058
1059 [[nodiscard]]
1060 constexpr const_iterator
1061 cbegin() const noexcept { return begin(); }
1062
1063 [[nodiscard]]
1064 constexpr const_iterator
1065 cend() const noexcept { return end(); }
1066
1067 [[nodiscard]]
1068 constexpr const_reverse_iterator
1069 crbegin() const noexcept { return rbegin(); }
1070
1071 [[nodiscard]]
1072 constexpr const_reverse_iterator
1073 crend() const noexcept { return rend(); }
1074
1075 // [containers.sequences.inplace.vector.members] size/capacity
1076 [[nodiscard]]
1077 constexpr bool
1078 empty() const noexcept { return true; }
1079
1080 [[nodiscard]]
1081 constexpr size_type
1082 size() const noexcept { return 0; }
1083
1084 [[nodiscard]]
1085 static constexpr size_type
1086 max_size() noexcept { return 0; }
1087
1088 [[nodiscard]]
1089 static constexpr size_type
1090 capacity() noexcept { return 0; }
1091
1092 constexpr void
1093 resize(size_type __n)
1094 {
1095 if (__n != 0)
1096 __throw_bad_alloc();
1097 }
1098
1099 constexpr void
1100 resize(size_type __n, const _Tp&)
1101 {
1102 if (__n != 0)
1103 __throw_bad_alloc();
1104 }
1105
1106 static constexpr void
1107 reserve(size_type __n)
1108 {
1109 if (__n != 0)
1110 __throw_bad_alloc();
1111 }
1112
1113 static constexpr void
1114 shrink_to_fit() { }
1115
1116 // element access
1117 [[nodiscard,noreturn]]
1118 constexpr reference
1119 operator[](size_type)
1120 { __builtin_trap(); }
1121
1122 [[nodiscard,noreturn]]
1123 constexpr const_reference
1124 operator[](size_type) const
1125 { __builtin_trap(); }
1126
1127 [[nodiscard,noreturn]]
1128 constexpr const_reference
1129 at(size_type __n) const
1130 {
1131 std::__throw_out_of_range_fmt(__N("inplace_vector::at: __n "
1132 "(which is %zu) "
1133 ">= size() (which is 0)"),
1134 __n);
1135 }
1136
1137 [[nodiscard,noreturn]]
1138 constexpr reference
1139 at(size_type __n)
1140 {
1141 std::__throw_out_of_range_fmt(__N("inplace_vector::at: __n "
1142 "(which is %zu) "
1143 ">= size() (which is 0)"),
1144 __n);
1145 }
1146
1147 [[nodiscard,noreturn]]
1148 constexpr reference
1149 front()
1150 { __builtin_trap(); }
1151
1152 [[nodiscard,noreturn]]
1153 constexpr const_reference
1154 front() const
1155 { __builtin_trap(); }
1156
1157 [[nodiscard,noreturn]]
1158 constexpr reference
1159 back()
1160 { __builtin_trap(); }
1161
1162 [[nodiscard,noreturn]]
1163 constexpr const_reference
1164 back() const
1165 { __builtin_trap(); }
1166
1167 // [containers.sequences.inplace.vector.data], data access
1168
1169 [[nodiscard]]
1170 constexpr _Tp*
1171 data() noexcept
1172 { return nullptr; }
1173
1174 [[nodiscard]]
1175 constexpr const _Tp*
1176 data() const noexcept
1177 { return nullptr; }
1178
1179 // [containers.sequences.inplace.vector.modifiers], modifiers
1180 template<typename... _Args>
1181 [[noreturn]]
1182 constexpr _Tp&
1183 emplace_back(_Args&&...)
1184 { __throw_bad_alloc(); }
1185
1186 [[noreturn]]
1187 constexpr _Tp&
1188 push_back(const _Tp&)
1189 { __throw_bad_alloc(); }
1190
1191 [[noreturn]]
1192 constexpr _Tp&
1193 push_back(_Tp&&)
1194 { __throw_bad_alloc(); }
1195
1196 template<__detail::__container_compatible_range<_Tp> _Rg>
1197 constexpr void
1198 append_range(_Rg&& __rg)
1199 {
1200 if (ranges::begin(__rg) != ranges::end(__rg))
1201 __throw_bad_alloc();
1202 }
1203
1204 [[noreturn]]
1205 constexpr void
1206 pop_back()
1207 { __builtin_trap(); }
1208
1209 template<typename... _Args>
1210 constexpr _Tp*
1211 try_emplace_back(_Args&&...)
1212 { return nullptr; }
1213
1214 constexpr _Tp*
1215 try_push_back(const _Tp&)
1216 { return nullptr; }
1217
1218 constexpr _Tp*
1219 try_push_back(_Tp&&)
1220 { return nullptr; }
1221
1222 template<__detail::__container_compatible_range<_Tp> _Rg>
1223 constexpr ranges::borrowed_iterator_t<_Rg>
1224 try_append_range(_Rg&& __rg)
1225 { return ranges::begin(__rg); }
1226
1227 template<typename... _Args>
1228 [[noreturn]]
1229 constexpr _Tp&
1230 unchecked_emplace_back(_Args&&...)
1231 { __builtin_trap(); }
1232
1233 [[noreturn]]
1234 constexpr _Tp&
1235 unchecked_push_back(const _Tp&)
1236 { __builtin_trap(); }
1237
1238 [[noreturn]]
1239 constexpr _Tp&
1240 unchecked_push_back(_Tp&&)
1241 { __builtin_trap(); }
1242
1243 template<typename... _Args>
1244 [[noreturn]]
1245 constexpr iterator
1246 emplace(const_iterator, _Args&&...)
1247 { __throw_bad_alloc(); }
1248
1249 [[noreturn]]
1250 constexpr iterator
1251 insert(const_iterator, const _Tp&)
1252 { __throw_bad_alloc(); }
1253
1254 [[noreturn]]
1255 constexpr iterator
1256 insert(const_iterator, _Tp&&)
1257 { __throw_bad_alloc(); }
1258
1259 constexpr iterator
1260 insert(const_iterator, size_type __n, const _Tp&)
1261 {
1262 if (__n != 0)
1263 __throw_bad_alloc();
1264 return begin();
1265 }
1266
1267 template<typename _InputIterator>
1268 constexpr iterator
1269 insert(const_iterator, _InputIterator __first, _InputIterator __last)
1270 {
1271 if (__first != __last)
1272 __throw_bad_alloc();
1273 return begin();
1274 }
1275
1276 template<__detail::__container_compatible_range<_Tp> _Rg>
1277 constexpr iterator
1278 insert_range(const_iterator, _Rg&& __rg)
1279 {
1280 if (ranges::begin(__rg) != ranges::end(__rg))
1281 __throw_bad_alloc();
1282 return begin();
1283 }
1284
1285 constexpr iterator
1286 insert(const_iterator, initializer_list<_Tp> __il)
1287 {
1288 if (__il.size() != 0)
1289 __throw_bad_alloc();
1290 return begin();
1291 }
1292
1293 [[noreturn]]
1294 constexpr iterator
1295 erase(const_iterator)
1296 { __builtin_trap(); }
1297
1298 constexpr iterator
1299 erase(const_iterator __first, const_iterator __last)
1300 {
1301 __glibcxx_assert(__first == __last);
1302 return begin();
1303 }
1304
1305 constexpr void
1306 swap(inplace_vector& __x)
1307 noexcept
1308 { }
1309
1310 constexpr void
1311 clear() noexcept
1312 { }
1313
1314 constexpr friend bool
1315 operator==(const inplace_vector&, const inplace_vector&)
1316 { return true; }
1317
1318 constexpr friend auto
1319 operator<=>(const inplace_vector&, const inplace_vector&)
1320 requires requires (const _Tp __t) {
1321 { __t < __t } -> __detail::__boolean_testable;
1322 }
1323 { return std::strong_ordering::equal; }
1324
1325 // n.b. there is not explicit wording requiring that swap for inplace_vector,
1326 // with zero size, works even if element type is not swappable. However given
1327 // that move operations are required to be present and trivial, it makes sense
1328 // to support them.
1329 constexpr friend void
1330 swap(inplace_vector&, inplace_vector&) noexcept
1331 { }
1332 };
1333
1334_GLIBCXX_END_NAMESPACE_CONTAINER
1335
1336 template<typename _Tp, size_t _Nm, typename _Predicate>
1337 constexpr size_t
1338 erase_if(_GLIBCXX_STD_C::inplace_vector<_Tp, _Nm>& __cont,
1339 _Predicate __pred)
1340 {
1341 if constexpr (_Nm != 0)
1342 {
1343 const auto __osz = __cont.size();
1344 const auto __end = __cont.end();
1345 auto __removed = std::__remove_if(__cont.begin(), __end,
1346 std::move(__pred));
1347 if (__removed != __end)
1348 {
1349 __cont.erase(__removed, __end);
1350 return __osz - __cont.size();
1351 }
1352 }
1353
1354 return 0;
1355 }
1356
1357 template<typename _Tp, size_t _Nm, typename _Up = _Tp>
1358 constexpr size_t
1359 erase(_GLIBCXX_STD_C::inplace_vector<_Tp, _Nm>& __cont, const _Up& __value)
1360 { return std::erase_if(__cont, __gnu_cxx::__ops::__equal_to(__value)); }
1361
1362_GLIBCXX_END_NAMESPACE_VERSION
1363} // namespace
1364
1365#ifdef _GLIBCXX_DEBUG
1366# include <debug/inplace_vector>
1367#endif
1368
1369#endif // __glibcxx_inplace_vector
1370#endif // _GLIBCXX_INPLACE_VECTOR
_ForwardIterator uninitialized_value_construct_n(_ForwardIterator __first, _Size __count)
Value-initializes objects in the range [first,first+count).
_ForwardIterator uninitialized_move(_InputIterator __first, _InputIterator __last, _ForwardIterator __result)
Move-construct from the range [first,last) into result.
_ForwardIterator uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp &__x)
Copies the value x into the range [first,first+n).
_ForwardIterator uninitialized_copy(_InputIterator __first, _InputIterator __last, _ForwardIterator __result)
Copies the range [first,last) into result.
__bool_constant< false > false_type
The type used as a compile-time boolean with false value.
Definition type_traits:122
constexpr _Tp * addressof(_Tp &__r) noexcept
Returns the actual address of the object or function referenced by r, even in the presence of an over...
Definition move.h:176
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition move.h:138
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
Definition move.h:72
constexpr auto lexicographical_compare_three_way(_InputIter1 __first1, _InputIter1 __last1, _InputIter2 __first2, _InputIter2 __last2, _Comp __comp) -> decltype(__comp(*__first1, *__first2))
Performs dictionary comparison on ranges.
ISO C++ entities toplevel namespace is std.
constexpr iterator_traits< _InputIterator >::difference_type distance(_InputIterator __first, _InputIterator __last)
A generalization of pointer arithmetic.
constexpr _ForwardIterator _Destroy_n(_ForwardIterator __first, _Size __count)