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