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