Back to home page

EIC code displayed by LXR

 
 

    


Warning, /include/c++/v1/__cxx03/__split_buffer is written in an unsupported language. File is not indexed.

0001 // -*- C++ -*-
0002 //===----------------------------------------------------------------------===//
0003 //
0004 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0005 // See https://llvm.org/LICENSE.txt for license information.
0006 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0007 //
0008 //===----------------------------------------------------------------------===//
0009 
0010 #ifndef _LIBCPP___CXX03___SPLIT_BUFFER
0011 #define _LIBCPP___CXX03___SPLIT_BUFFER
0012 
0013 #include <__cxx03/__algorithm/max.h>
0014 #include <__cxx03/__algorithm/move.h>
0015 #include <__cxx03/__algorithm/move_backward.h>
0016 #include <__cxx03/__config>
0017 #include <__cxx03/__iterator/distance.h>
0018 #include <__cxx03/__iterator/iterator_traits.h>
0019 #include <__cxx03/__iterator/move_iterator.h>
0020 #include <__cxx03/__memory/allocate_at_least.h>
0021 #include <__cxx03/__memory/allocator.h>
0022 #include <__cxx03/__memory/allocator_traits.h>
0023 #include <__cxx03/__memory/compressed_pair.h>
0024 #include <__cxx03/__memory/pointer_traits.h>
0025 #include <__cxx03/__memory/swap_allocator.h>
0026 #include <__cxx03/__type_traits/add_lvalue_reference.h>
0027 #include <__cxx03/__type_traits/conditional.h>
0028 #include <__cxx03/__type_traits/enable_if.h>
0029 #include <__cxx03/__type_traits/integral_constant.h>
0030 #include <__cxx03/__type_traits/is_nothrow_assignable.h>
0031 #include <__cxx03/__type_traits/is_nothrow_constructible.h>
0032 #include <__cxx03/__type_traits/is_swappable.h>
0033 #include <__cxx03/__type_traits/is_trivially_destructible.h>
0034 #include <__cxx03/__type_traits/is_trivially_relocatable.h>
0035 #include <__cxx03/__type_traits/remove_reference.h>
0036 #include <__cxx03/__utility/forward.h>
0037 #include <__cxx03/__utility/move.h>
0038 #include <__cxx03/cstddef>
0039 
0040 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0041 #  pragma GCC system_header
0042 #endif
0043 
0044 _LIBCPP_PUSH_MACROS
0045 #include <__cxx03/__undef_macros>
0046 
0047 _LIBCPP_BEGIN_NAMESPACE_STD
0048 
0049 // __split_buffer allocates a contiguous chunk of memory and stores objects in the range [__begin_, __end_).
0050 // It has uninitialized memory in the ranges  [__first_, __begin_) and [__end_, __end_cap_.first()). That allows
0051 // it to grow both in the front and back without having to move the data.
0052 
0053 template <class _Tp, class _Allocator = allocator<_Tp> >
0054 struct __split_buffer {
0055 public:
0056   using value_type      = _Tp;
0057   using allocator_type  = _Allocator;
0058   using __alloc_rr      = __libcpp_remove_reference_t<allocator_type>;
0059   using __alloc_traits  = allocator_traits<__alloc_rr>;
0060   using reference       = value_type&;
0061   using const_reference = const value_type&;
0062   using size_type       = typename __alloc_traits::size_type;
0063   using difference_type = typename __alloc_traits::difference_type;
0064   using pointer         = typename __alloc_traits::pointer;
0065   using const_pointer   = typename __alloc_traits::const_pointer;
0066   using iterator        = pointer;
0067   using const_iterator  = const_pointer;
0068 
0069   // A __split_buffer contains the following members which may be trivially relocatable:
0070   // - pointer: may be trivially relocatable, so it's checked
0071   // - allocator_type: may be trivially relocatable, so it's checked
0072   // __split_buffer doesn't have any self-references, so it's trivially relocatable if its members are.
0073   using __trivially_relocatable = __conditional_t<
0074       __libcpp_is_trivially_relocatable<pointer>::value && __libcpp_is_trivially_relocatable<allocator_type>::value,
0075       __split_buffer,
0076       void>;
0077 
0078   pointer __first_;
0079   pointer __begin_;
0080   pointer __end_;
0081   __compressed_pair<pointer, allocator_type> __end_cap_;
0082 
0083   using __alloc_ref       = __add_lvalue_reference_t<allocator_type>;
0084   using __alloc_const_ref = __add_lvalue_reference_t<allocator_type>;
0085 
0086   __split_buffer(const __split_buffer&)            = delete;
0087   __split_buffer& operator=(const __split_buffer&) = delete;
0088 
0089   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer()
0090       _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
0091       : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr, __default_init_tag()) {}
0092 
0093   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(__alloc_rr& __a)
0094       : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr, __a) {}
0095 
0096   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(const __alloc_rr& __a)
0097       : __first_(nullptr), __begin_(nullptr), __end_(nullptr), __end_cap_(nullptr, __a) {}
0098 
0099   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
0100   __split_buffer(size_type __cap, size_type __start, __alloc_rr& __a);
0101 
0102   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer(__split_buffer&& __c)
0103       _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value);
0104 
0105   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer(__split_buffer&& __c, const __alloc_rr& __a);
0106 
0107   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer& operator=(__split_buffer&& __c)
0108       _NOEXCEPT_((__alloc_traits::propagate_on_container_move_assignment::value &&
0109                   is_nothrow_move_assignable<allocator_type>::value) ||
0110                  !__alloc_traits::propagate_on_container_move_assignment::value);
0111 
0112   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~__split_buffer();
0113 
0114   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __alloc_rr& __alloc() _NOEXCEPT { return __end_cap_.second(); }
0115   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const __alloc_rr& __alloc() const _NOEXCEPT {
0116     return __end_cap_.second();
0117   }
0118 
0119   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer& __end_cap() _NOEXCEPT { return __end_cap_.first(); }
0120   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const pointer& __end_cap() const _NOEXCEPT {
0121     return __end_cap_.first();
0122   }
0123 
0124   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return __begin_; }
0125   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return __begin_; }
0126 
0127   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return __end_; }
0128   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return __end_; }
0129 
0130   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT { __destruct_at_end(__begin_); }
0131 
0132   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const {
0133     return static_cast<size_type>(__end_ - __begin_);
0134   }
0135 
0136   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const { return __end_ == __begin_; }
0137 
0138   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const {
0139     return static_cast<size_type>(__end_cap() - __first_);
0140   }
0141 
0142   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __front_spare() const {
0143     return static_cast<size_type>(__begin_ - __first_);
0144   }
0145 
0146   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __back_spare() const {
0147     return static_cast<size_type>(__end_cap() - __end_);
0148   }
0149 
0150   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference front() { return *__begin_; }
0151   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference front() const { return *__begin_; }
0152   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() { return *(__end_ - 1); }
0153   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const { return *(__end_ - 1); }
0154 
0155   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void reserve(size_type __n);
0156   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void shrink_to_fit() _NOEXCEPT;
0157   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_front(const_reference __x);
0158   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_back(const_reference __x);
0159   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_front(value_type&& __x);
0160   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void push_back(value_type&& __x);
0161 
0162   template <class... _Args>
0163   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void emplace_back(_Args&&... __args);
0164 
0165   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_front() { __destruct_at_begin(__begin_ + 1); }
0166   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_back() { __destruct_at_end(__end_ - 1); }
0167 
0168   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_at_end(size_type __n);
0169   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_at_end(size_type __n, const_reference __x);
0170 
0171   template <class _InputIter, __enable_if_t<__has_exactly_input_iterator_category<_InputIter>::value, int> = 0>
0172   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_at_end(_InputIter __first, _InputIter __last);
0173 
0174   template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0>
0175   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
0176   __construct_at_end(_ForwardIterator __first, _ForwardIterator __last);
0177 
0178   template <class _Iterator, class _Sentinel>
0179   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
0180   __construct_at_end_with_sentinel(_Iterator __first, _Sentinel __last);
0181 
0182   template <class _Iterator>
0183   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
0184   __construct_at_end_with_size(_Iterator __first, size_type __n);
0185 
0186   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_begin(pointer __new_begin) {
0187     __destruct_at_begin(__new_begin, is_trivially_destructible<value_type>());
0188   }
0189 
0190   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_begin(pointer __new_begin, false_type);
0191   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_begin(pointer __new_begin, true_type);
0192 
0193   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_end(pointer __new_last) _NOEXCEPT {
0194     __destruct_at_end(__new_last, false_type());
0195   }
0196 
0197   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_end(pointer __new_last, false_type) _NOEXCEPT;
0198   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_end(pointer __new_last, true_type) _NOEXCEPT;
0199 
0200   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__split_buffer& __x)
0201       _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__alloc_rr>);
0202 
0203   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const;
0204 
0205 private:
0206   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__split_buffer& __c, true_type)
0207       _NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) {
0208     __alloc() = std::move(__c.__alloc());
0209   }
0210 
0211   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__split_buffer&, false_type) _NOEXCEPT {}
0212 
0213   struct _ConstructTransaction {
0214     _LIBCPP_CONSTEXPR_SINCE_CXX20
0215     _LIBCPP_HIDE_FROM_ABI explicit _ConstructTransaction(pointer* __p, size_type __n) _NOEXCEPT
0216         : __pos_(*__p),
0217           __end_(*__p + __n),
0218           __dest_(__p) {}
0219 
0220     _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~_ConstructTransaction() { *__dest_ = __pos_; }
0221 
0222     pointer __pos_;
0223     const pointer __end_;
0224 
0225   private:
0226     pointer* __dest_;
0227   };
0228 };
0229 
0230 template <class _Tp, class _Allocator>
0231 _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __split_buffer<_Tp, _Allocator>::__invariants() const {
0232   if (__first_ == nullptr) {
0233     if (__begin_ != nullptr)
0234       return false;
0235     if (__end_ != nullptr)
0236       return false;
0237     if (__end_cap() != nullptr)
0238       return false;
0239   } else {
0240     if (__begin_ < __first_)
0241       return false;
0242     if (__end_ < __begin_)
0243       return false;
0244     if (__end_cap() < __end_)
0245       return false;
0246   }
0247   return true;
0248 }
0249 
0250 //  Default constructs __n objects starting at __end_
0251 //  throws if construction throws
0252 //  Precondition:  __n > 0
0253 //  Precondition:  size() + __n <= capacity()
0254 //  Postcondition:  size() == size() + __n
0255 template <class _Tp, class _Allocator>
0256 _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n) {
0257   _ConstructTransaction __tx(&this->__end_, __n);
0258   for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) {
0259     __alloc_traits::construct(this->__alloc(), std::__to_address(__tx.__pos_));
0260   }
0261 }
0262 
0263 //  Copy constructs __n objects starting at __end_ from __x
0264 //  throws if construction throws
0265 //  Precondition:  __n > 0
0266 //  Precondition:  size() + __n <= capacity()
0267 //  Postcondition:  size() == old size() + __n
0268 //  Postcondition:  [i] == __x for all i in [size() - __n, __n)
0269 template <class _Tp, class _Allocator>
0270 _LIBCPP_CONSTEXPR_SINCE_CXX20 void
0271 __split_buffer<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x) {
0272   _ConstructTransaction __tx(&this->__end_, __n);
0273   for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) {
0274     __alloc_traits::construct(this->__alloc(), std::__to_address(__tx.__pos_), __x);
0275   }
0276 }
0277 
0278 template <class _Tp, class _Allocator>
0279 template <class _InputIter, __enable_if_t<__has_exactly_input_iterator_category<_InputIter>::value, int> >
0280 _LIBCPP_CONSTEXPR_SINCE_CXX20 void
0281 __split_buffer<_Tp, _Allocator>::__construct_at_end(_InputIter __first, _InputIter __last) {
0282   __construct_at_end_with_sentinel(__first, __last);
0283 }
0284 
0285 template <class _Tp, class _Allocator>
0286 template <class _Iterator, class _Sentinel>
0287 _LIBCPP_CONSTEXPR_SINCE_CXX20 void
0288 __split_buffer<_Tp, _Allocator>::__construct_at_end_with_sentinel(_Iterator __first, _Sentinel __last) {
0289   __alloc_rr& __a = this->__alloc();
0290   for (; __first != __last; ++__first) {
0291     if (__end_ == __end_cap()) {
0292       size_type __old_cap = __end_cap() - __first_;
0293       size_type __new_cap = std::max<size_type>(2 * __old_cap, 8);
0294       __split_buffer __buf(__new_cap, 0, __a);
0295       for (pointer __p = __begin_; __p != __end_; ++__p, (void)++__buf.__end_)
0296         __alloc_traits::construct(__buf.__alloc(), std::__to_address(__buf.__end_), std::move(*__p));
0297       swap(__buf);
0298     }
0299     __alloc_traits::construct(__a, std::__to_address(this->__end_), *__first);
0300     ++this->__end_;
0301   }
0302 }
0303 template <class _Tp, class _Allocator>
0304 template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> >
0305 _LIBCPP_CONSTEXPR_SINCE_CXX20 void
0306 __split_buffer<_Tp, _Allocator>::__construct_at_end(_ForwardIterator __first, _ForwardIterator __last) {
0307   __construct_at_end_with_size(__first, std::distance(__first, __last));
0308 }
0309 
0310 template <class _Tp, class _Allocator>
0311 template <class _ForwardIterator>
0312 _LIBCPP_CONSTEXPR_SINCE_CXX20 void
0313 __split_buffer<_Tp, _Allocator>::__construct_at_end_with_size(_ForwardIterator __first, size_type __n) {
0314   _ConstructTransaction __tx(&this->__end_, __n);
0315   for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_, (void)++__first) {
0316     __alloc_traits::construct(this->__alloc(), std::__to_address(__tx.__pos_), *__first);
0317   }
0318 }
0319 
0320 template <class _Tp, class _Allocator>
0321 _LIBCPP_CONSTEXPR_SINCE_CXX20 inline void
0322 __split_buffer<_Tp, _Allocator>::__destruct_at_begin(pointer __new_begin, false_type) {
0323   while (__begin_ != __new_begin)
0324     __alloc_traits::destroy(__alloc(), std::__to_address(__begin_++));
0325 }
0326 
0327 template <class _Tp, class _Allocator>
0328 _LIBCPP_CONSTEXPR_SINCE_CXX20 inline void
0329 __split_buffer<_Tp, _Allocator>::__destruct_at_begin(pointer __new_begin, true_type) {
0330   __begin_ = __new_begin;
0331 }
0332 
0333 template <class _Tp, class _Allocator>
0334 _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI void
0335 __split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, false_type) _NOEXCEPT {
0336   while (__new_last != __end_)
0337     __alloc_traits::destroy(__alloc(), std::__to_address(--__end_));
0338 }
0339 
0340 template <class _Tp, class _Allocator>
0341 _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI void
0342 __split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, true_type) _NOEXCEPT {
0343   __end_ = __new_last;
0344 }
0345 
0346 template <class _Tp, class _Allocator>
0347 _LIBCPP_CONSTEXPR_SINCE_CXX20
0348 __split_buffer<_Tp, _Allocator>::__split_buffer(size_type __cap, size_type __start, __alloc_rr& __a)
0349     : __end_cap_(nullptr, __a) {
0350   if (__cap == 0) {
0351     __first_ = nullptr;
0352   } else {
0353     auto __allocation = std::__allocate_at_least(__alloc(), __cap);
0354     __first_          = __allocation.ptr;
0355     __cap             = __allocation.count;
0356   }
0357   __begin_ = __end_ = __first_ + __start;
0358   __end_cap()       = __first_ + __cap;
0359 }
0360 
0361 template <class _Tp, class _Allocator>
0362 _LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator>::~__split_buffer() {
0363   clear();
0364   if (__first_)
0365     __alloc_traits::deallocate(__alloc(), __first_, capacity());
0366 }
0367 
0368 template <class _Tp, class _Allocator>
0369 _LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c)
0370     _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
0371     : __first_(std::move(__c.__first_)),
0372       __begin_(std::move(__c.__begin_)),
0373       __end_(std::move(__c.__end_)),
0374       __end_cap_(std::move(__c.__end_cap_)) {
0375   __c.__first_    = nullptr;
0376   __c.__begin_    = nullptr;
0377   __c.__end_      = nullptr;
0378   __c.__end_cap() = nullptr;
0379 }
0380 
0381 template <class _Tp, class _Allocator>
0382 _LIBCPP_CONSTEXPR_SINCE_CXX20
0383 __split_buffer<_Tp, _Allocator>::__split_buffer(__split_buffer&& __c, const __alloc_rr& __a)
0384     : __end_cap_(nullptr, __a) {
0385   if (__a == __c.__alloc()) {
0386     __first_        = __c.__first_;
0387     __begin_        = __c.__begin_;
0388     __end_          = __c.__end_;
0389     __end_cap()     = __c.__end_cap();
0390     __c.__first_    = nullptr;
0391     __c.__begin_    = nullptr;
0392     __c.__end_      = nullptr;
0393     __c.__end_cap() = nullptr;
0394   } else {
0395     auto __allocation = std::__allocate_at_least(__alloc(), __c.size());
0396     __first_          = __allocation.ptr;
0397     __begin_ = __end_ = __first_;
0398     __end_cap()       = __first_ + __allocation.count;
0399     typedef move_iterator<iterator> _Ip;
0400     __construct_at_end(_Ip(__c.begin()), _Ip(__c.end()));
0401   }
0402 }
0403 
0404 template <class _Tp, class _Allocator>
0405 _LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator>&
0406 __split_buffer<_Tp, _Allocator>::operator=(__split_buffer&& __c)
0407     _NOEXCEPT_((__alloc_traits::propagate_on_container_move_assignment::value &&
0408                 is_nothrow_move_assignable<allocator_type>::value) ||
0409                !__alloc_traits::propagate_on_container_move_assignment::value) {
0410   clear();
0411   shrink_to_fit();
0412   __first_    = __c.__first_;
0413   __begin_    = __c.__begin_;
0414   __end_      = __c.__end_;
0415   __end_cap() = __c.__end_cap();
0416   __move_assign_alloc(__c, integral_constant<bool, __alloc_traits::propagate_on_container_move_assignment::value>());
0417   __c.__first_ = __c.__begin_ = __c.__end_ = __c.__end_cap() = nullptr;
0418   return *this;
0419 }
0420 
0421 template <class _Tp, class _Allocator>
0422 _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::swap(__split_buffer& __x)
0423     _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__alloc_rr>) {
0424   std::swap(__first_, __x.__first_);
0425   std::swap(__begin_, __x.__begin_);
0426   std::swap(__end_, __x.__end_);
0427   std::swap(__end_cap(), __x.__end_cap());
0428   std::__swap_allocator(__alloc(), __x.__alloc());
0429 }
0430 
0431 template <class _Tp, class _Allocator>
0432 _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::reserve(size_type __n) {
0433   if (__n < capacity()) {
0434     __split_buffer<value_type, __alloc_rr&> __t(__n, 0, __alloc());
0435     __t.__construct_at_end(move_iterator<pointer>(__begin_), move_iterator<pointer>(__end_));
0436     std::swap(__first_, __t.__first_);
0437     std::swap(__begin_, __t.__begin_);
0438     std::swap(__end_, __t.__end_);
0439     std::swap(__end_cap(), __t.__end_cap());
0440   }
0441 }
0442 
0443 template <class _Tp, class _Allocator>
0444 _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::shrink_to_fit() _NOEXCEPT {
0445   if (capacity() > size()) {
0446 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
0447     try {
0448 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
0449       __split_buffer<value_type, __alloc_rr&> __t(size(), 0, __alloc());
0450       __t.__construct_at_end(move_iterator<pointer>(__begin_), move_iterator<pointer>(__end_));
0451       __t.__end_ = __t.__begin_ + (__end_ - __begin_);
0452       std::swap(__first_, __t.__first_);
0453       std::swap(__begin_, __t.__begin_);
0454       std::swap(__end_, __t.__end_);
0455       std::swap(__end_cap(), __t.__end_cap());
0456 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
0457     } catch (...) {
0458     }
0459 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
0460   }
0461 }
0462 
0463 template <class _Tp, class _Allocator>
0464 _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::push_front(const_reference __x) {
0465   if (__begin_ == __first_) {
0466     if (__end_ < __end_cap()) {
0467       difference_type __d = __end_cap() - __end_;
0468       __d                 = (__d + 1) / 2;
0469       __begin_            = std::move_backward(__begin_, __end_, __end_ + __d);
0470       __end_ += __d;
0471     } else {
0472       size_type __c = std::max<size_type>(2 * static_cast<size_t>(__end_cap() - __first_), 1);
0473       __split_buffer<value_type, __alloc_rr&> __t(__c, (__c + 3) / 4, __alloc());
0474       __t.__construct_at_end(move_iterator<pointer>(__begin_), move_iterator<pointer>(__end_));
0475       std::swap(__first_, __t.__first_);
0476       std::swap(__begin_, __t.__begin_);
0477       std::swap(__end_, __t.__end_);
0478       std::swap(__end_cap(), __t.__end_cap());
0479     }
0480   }
0481   __alloc_traits::construct(__alloc(), std::__to_address(__begin_ - 1), __x);
0482   --__begin_;
0483 }
0484 
0485 template <class _Tp, class _Allocator>
0486 _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::push_front(value_type&& __x) {
0487   if (__begin_ == __first_) {
0488     if (__end_ < __end_cap()) {
0489       difference_type __d = __end_cap() - __end_;
0490       __d                 = (__d + 1) / 2;
0491       __begin_            = std::move_backward(__begin_, __end_, __end_ + __d);
0492       __end_ += __d;
0493     } else {
0494       size_type __c = std::max<size_type>(2 * static_cast<size_t>(__end_cap() - __first_), 1);
0495       __split_buffer<value_type, __alloc_rr&> __t(__c, (__c + 3) / 4, __alloc());
0496       __t.__construct_at_end(move_iterator<pointer>(__begin_), move_iterator<pointer>(__end_));
0497       std::swap(__first_, __t.__first_);
0498       std::swap(__begin_, __t.__begin_);
0499       std::swap(__end_, __t.__end_);
0500       std::swap(__end_cap(), __t.__end_cap());
0501     }
0502   }
0503   __alloc_traits::construct(__alloc(), std::__to_address(__begin_ - 1), std::move(__x));
0504   --__begin_;
0505 }
0506 
0507 template <class _Tp, class _Allocator>
0508 _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI void
0509 __split_buffer<_Tp, _Allocator>::push_back(const_reference __x) {
0510   if (__end_ == __end_cap()) {
0511     if (__begin_ > __first_) {
0512       difference_type __d = __begin_ - __first_;
0513       __d                 = (__d + 1) / 2;
0514       __end_              = std::move(__begin_, __end_, __begin_ - __d);
0515       __begin_ -= __d;
0516     } else {
0517       size_type __c = std::max<size_type>(2 * static_cast<size_t>(__end_cap() - __first_), 1);
0518       __split_buffer<value_type, __alloc_rr&> __t(__c, __c / 4, __alloc());
0519       __t.__construct_at_end(move_iterator<pointer>(__begin_), move_iterator<pointer>(__end_));
0520       std::swap(__first_, __t.__first_);
0521       std::swap(__begin_, __t.__begin_);
0522       std::swap(__end_, __t.__end_);
0523       std::swap(__end_cap(), __t.__end_cap());
0524     }
0525   }
0526   __alloc_traits::construct(__alloc(), std::__to_address(__end_), __x);
0527   ++__end_;
0528 }
0529 
0530 template <class _Tp, class _Allocator>
0531 _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::push_back(value_type&& __x) {
0532   if (__end_ == __end_cap()) {
0533     if (__begin_ > __first_) {
0534       difference_type __d = __begin_ - __first_;
0535       __d                 = (__d + 1) / 2;
0536       __end_              = std::move(__begin_, __end_, __begin_ - __d);
0537       __begin_ -= __d;
0538     } else {
0539       size_type __c = std::max<size_type>(2 * static_cast<size_t>(__end_cap() - __first_), 1);
0540       __split_buffer<value_type, __alloc_rr&> __t(__c, __c / 4, __alloc());
0541       __t.__construct_at_end(move_iterator<pointer>(__begin_), move_iterator<pointer>(__end_));
0542       std::swap(__first_, __t.__first_);
0543       std::swap(__begin_, __t.__begin_);
0544       std::swap(__end_, __t.__end_);
0545       std::swap(__end_cap(), __t.__end_cap());
0546     }
0547   }
0548   __alloc_traits::construct(__alloc(), std::__to_address(__end_), std::move(__x));
0549   ++__end_;
0550 }
0551 
0552 template <class _Tp, class _Allocator>
0553 template <class... _Args>
0554 _LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator>::emplace_back(_Args&&... __args) {
0555   if (__end_ == __end_cap()) {
0556     if (__begin_ > __first_) {
0557       difference_type __d = __begin_ - __first_;
0558       __d                 = (__d + 1) / 2;
0559       __end_              = std::move(__begin_, __end_, __begin_ - __d);
0560       __begin_ -= __d;
0561     } else {
0562       size_type __c = std::max<size_type>(2 * static_cast<size_t>(__end_cap() - __first_), 1);
0563       __split_buffer<value_type, __alloc_rr&> __t(__c, __c / 4, __alloc());
0564       __t.__construct_at_end(move_iterator<pointer>(__begin_), move_iterator<pointer>(__end_));
0565       std::swap(__first_, __t.__first_);
0566       std::swap(__begin_, __t.__begin_);
0567       std::swap(__end_, __t.__end_);
0568       std::swap(__end_cap(), __t.__end_cap());
0569     }
0570   }
0571   __alloc_traits::construct(__alloc(), std::__to_address(__end_), std::forward<_Args>(__args)...);
0572   ++__end_;
0573 }
0574 
0575 template <class _Tp, class _Allocator>
0576 _LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI void
0577 swap(__split_buffer<_Tp, _Allocator>& __x, __split_buffer<_Tp, _Allocator>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) {
0578   __x.swap(__y);
0579 }
0580 
0581 _LIBCPP_END_NAMESPACE_STD
0582 
0583 _LIBCPP_POP_MACROS
0584 
0585 #endif // _LIBCPP___CXX03___SPLIT_BUFFER