mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-27 19:09:47 +03:00
860 lines
36 KiB
C++
Vendored
860 lines
36 KiB
C++
Vendored
// -*- C++ -*-
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef _LIBCPP___SPLIT_BUFFER
|
|
#define _LIBCPP___SPLIT_BUFFER
|
|
|
|
#include <__algorithm/max.h>
|
|
#include <__algorithm/move.h>
|
|
#include <__algorithm/move_backward.h>
|
|
#include <__assert>
|
|
#include <__config>
|
|
#include <__iterator/distance.h>
|
|
#include <__iterator/iterator_traits.h>
|
|
#include <__iterator/move_iterator.h>
|
|
#include <__memory/addressof.h>
|
|
#include <__memory/allocate_at_least.h>
|
|
#include <__memory/allocator.h>
|
|
#include <__memory/allocator_traits.h>
|
|
#include <__memory/compressed_pair.h>
|
|
#include <__memory/pointer_traits.h>
|
|
#include <__memory/swap_allocator.h>
|
|
#include <__type_traits/conditional.h>
|
|
#include <__type_traits/enable_if.h>
|
|
#include <__type_traits/integral_constant.h>
|
|
#include <__type_traits/is_nothrow_assignable.h>
|
|
#include <__type_traits/is_nothrow_constructible.h>
|
|
#include <__type_traits/is_swappable.h>
|
|
#include <__type_traits/is_trivially_destructible.h>
|
|
#include <__type_traits/is_trivially_relocatable.h>
|
|
#include <__utility/forward.h>
|
|
#include <__utility/move.h>
|
|
|
|
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
|
# pragma GCC system_header
|
|
#endif
|
|
|
|
_LIBCPP_PUSH_MACROS
|
|
#include <__undef_macros>
|
|
|
|
_LIBCPP_BEGIN_NAMESPACE_STD
|
|
|
|
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
|
|
class __split_buffer;
|
|
|
|
template <class _SplitBuffer, class _Tp, class _Allocator>
|
|
class __split_buffer_pointer_layout {
|
|
protected:
|
|
using value_type = _Tp;
|
|
using allocator_type = _Allocator;
|
|
using __alloc_traits _LIBCPP_NODEBUG = allocator_traits<allocator_type>;
|
|
using reference = value_type&;
|
|
using const_reference = const value_type&;
|
|
using size_type = typename __alloc_traits::size_type;
|
|
using difference_type = typename __alloc_traits::difference_type;
|
|
using pointer = typename __alloc_traits::pointer;
|
|
using const_pointer = typename __alloc_traits::const_pointer;
|
|
using iterator = pointer;
|
|
using const_iterator = const_pointer;
|
|
using __sentinel_type _LIBCPP_NODEBUG = pointer;
|
|
|
|
public:
|
|
// Can't be defaulted due to _LIBCPP_COMPRESSED_PAIR not being an aggregate in C++03 and C++11.
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer_pointer_layout() : __back_cap_(nullptr) {}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20
|
|
_LIBCPP_HIDE_FROM_ABI explicit __split_buffer_pointer_layout(const allocator_type& __alloc)
|
|
: __back_cap_(nullptr), __alloc_(__alloc) {}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __front_cap() _NOEXCEPT { return __front_cap_; }
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer __front_cap() const _NOEXCEPT {
|
|
return __front_cap_;
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer begin() _NOEXCEPT { return __begin_; }
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer begin() const _NOEXCEPT { return __begin_; }
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() _NOEXCEPT { return __end_; }
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() const _NOEXCEPT { return __end_; }
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT {
|
|
return static_cast<size_type>(__end_ - __begin_);
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return __begin_ == __end_; }
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT {
|
|
return static_cast<size_type>(__back_cap_ - __front_cap_);
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type& __get_allocator() _NOEXCEPT { return __alloc_; }
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type const& __get_allocator() const _NOEXCEPT {
|
|
return __alloc_;
|
|
}
|
|
|
|
// Returns the sentinel object directly. Should be used in conjunction with automatic type deduction,
|
|
// not explicit types.
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __sentinel_type __raw_sentinel() const _NOEXCEPT {
|
|
return __end_;
|
|
}
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __sentinel_type __raw_capacity() const _NOEXCEPT {
|
|
return __back_cap_;
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_data(pointer __new_first) _NOEXCEPT {
|
|
__front_cap_ = __new_first;
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
|
|
__set_valid_range(pointer __new_begin, pointer __new_end) _NOEXCEPT {
|
|
__begin_ = __new_begin;
|
|
__end_ = __new_end;
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
|
|
__set_valid_range(pointer __new_begin, size_type __new_size) _NOEXCEPT {
|
|
__begin_ = __new_begin;
|
|
__end_ = __begin_ + __new_size;
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __new_end) _NOEXCEPT {
|
|
_LIBCPP_ASSERT_INTERNAL(__front_cap_ <= __new_end, "__new_end cannot precede __front_cap_");
|
|
__end_ = __new_end;
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(size_type __new_size) _NOEXCEPT {
|
|
__end_ = __begin_ + __new_size;
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __new_capacity) _NOEXCEPT {
|
|
__back_cap_ = __front_cap_ + __new_capacity;
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __new_capacity) _NOEXCEPT {
|
|
__back_cap_ = __new_capacity;
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __front_spare() const _NOEXCEPT {
|
|
return static_cast<size_type>(__begin_ - __front_cap_);
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __back_spare() const _NOEXCEPT {
|
|
return static_cast<size_type>(__back_cap_ - __end_);
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT { return *(__end_ - 1); }
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT { return *(__end_ - 1); }
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_without_allocator(
|
|
__split_buffer_pointer_layout<__split_buffer<value_type, allocator_type, __split_buffer_pointer_layout>,
|
|
value_type,
|
|
allocator_type>& __other) _NOEXCEPT {
|
|
std::swap(__front_cap_, __other.__front_cap_);
|
|
std::swap(__begin_, __other.__begin_);
|
|
std::swap(__back_cap_, __other.__back_cap_);
|
|
std::swap(__end_, __other.__end_);
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__split_buffer_pointer_layout& __other) _NOEXCEPT {
|
|
std::swap(__front_cap_, __other.__front_cap_);
|
|
std::swap(__begin_, __other.__begin_);
|
|
std::swap(__back_cap_, __other.__back_cap_);
|
|
std::swap(__end_, __other.__end_);
|
|
std::__swap_allocator(__alloc_, __other.__alloc_);
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __reset() _NOEXCEPT {
|
|
__front_cap_ = nullptr;
|
|
__begin_ = nullptr;
|
|
__end_ = nullptr;
|
|
__back_cap_ = nullptr;
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
|
|
__copy_without_alloc(__split_buffer_pointer_layout const& __other)
|
|
_NOEXCEPT_(is_nothrow_copy_assignable<pointer>::value) {
|
|
__front_cap_ = __other.__front_cap_;
|
|
__begin_ = __other.__begin_;
|
|
__end_ = __other.__end_;
|
|
__back_cap_ = __other.__back_cap_;
|
|
}
|
|
|
|
private:
|
|
pointer __front_cap_ = nullptr;
|
|
pointer __begin_ = nullptr;
|
|
pointer __end_ = nullptr;
|
|
_LIBCPP_COMPRESSED_PAIR(pointer, __back_cap_, allocator_type, __alloc_);
|
|
|
|
template <class, class, class>
|
|
friend class __split_buffer_pointer_layout;
|
|
};
|
|
|
|
template <class _SplitBuffer, class _Tp, class _Allocator>
|
|
class __split_buffer_size_layout {
|
|
protected:
|
|
using value_type = _Tp;
|
|
using allocator_type = _Allocator;
|
|
using __alloc_traits _LIBCPP_NODEBUG = allocator_traits<allocator_type>;
|
|
using reference = value_type&;
|
|
using const_reference = const value_type&;
|
|
using size_type = typename __alloc_traits::size_type;
|
|
using difference_type = typename __alloc_traits::difference_type;
|
|
using pointer = typename __alloc_traits::pointer;
|
|
using const_pointer = typename __alloc_traits::const_pointer;
|
|
using iterator = pointer;
|
|
using const_iterator = const_pointer;
|
|
using __sentinel_type _LIBCPP_NODEBUG = size_type;
|
|
|
|
public:
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer_size_layout() = default;
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer_size_layout(const allocator_type& __alloc)
|
|
: __alloc_(__alloc) {}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer __front_cap() _NOEXCEPT { return __front_cap_; }
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer __front_cap() const _NOEXCEPT {
|
|
return __front_cap_;
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer begin() _NOEXCEPT { return __begin_; }
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_pointer begin() const _NOEXCEPT { return __begin_; }
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() _NOEXCEPT { return __begin_ + __size_; }
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pointer end() const _NOEXCEPT { return __begin_ + __size_; }
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __size_; }
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return __size_ == 0; }
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type capacity() const _NOEXCEPT { return __cap_; }
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type& __get_allocator() _NOEXCEPT { return __alloc_; }
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI allocator_type const& __get_allocator() const _NOEXCEPT {
|
|
return __alloc_;
|
|
}
|
|
|
|
// Returns the sentinel object directly. Should be used in conjunction with automatic type deduction,
|
|
// not explicit types.
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __sentinel_type __raw_sentinel() const _NOEXCEPT {
|
|
return __size_;
|
|
}
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __sentinel_type __raw_capacity() const _NOEXCEPT {
|
|
return __cap_;
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_data(pointer __new_first) _NOEXCEPT {
|
|
__front_cap_ = __new_first;
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
|
|
__set_valid_range(pointer __new_begin, pointer __new_end) _NOEXCEPT {
|
|
// Size-based __split_buffers track their size directly: we need to explicitly update the size
|
|
// when the front is adjusted.
|
|
__size_ -= __new_begin - __begin_;
|
|
__begin_ = __new_begin;
|
|
__set_sentinel(__new_end);
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
|
|
__set_valid_range(pointer __new_begin, size_type __new_size) _NOEXCEPT {
|
|
// Size-based __split_buffers track their size directly: we need to explicitly update the size
|
|
// when the front is adjusted.
|
|
__size_ -= __new_begin - __begin_;
|
|
__begin_ = __new_begin;
|
|
__set_sentinel(__new_size);
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(pointer __new_end) _NOEXCEPT {
|
|
_LIBCPP_ASSERT_INTERNAL(__front_cap_ <= __new_end, "__new_end cannot precede __front_cap_");
|
|
__size_ += __new_end - end();
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_sentinel(size_type __new_size) _NOEXCEPT {
|
|
__size_ = __new_size;
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(size_type __new_capacity) _NOEXCEPT {
|
|
__cap_ = __new_capacity;
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __set_capacity(pointer __new_capacity) _NOEXCEPT {
|
|
__cap_ = __new_capacity - __begin_;
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __front_spare() const _NOEXCEPT {
|
|
return static_cast<size_type>(__begin_ - __front_cap_);
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI size_type __back_spare() const _NOEXCEPT {
|
|
// `__cap_ - __end_` tells us the total number of spares when in size-mode. We need to remove
|
|
// the __front_spare from the count.
|
|
return __cap_ - __size_ - __front_spare();
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference back() _NOEXCEPT { return __begin_[__size_ - 1]; }
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference back() const _NOEXCEPT {
|
|
return __begin_[__size_ - 1];
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __swap_without_allocator(
|
|
__split_buffer_pointer_layout<__split_buffer<value_type, allocator_type, __split_buffer_pointer_layout>,
|
|
value_type,
|
|
allocator_type>& __other) _NOEXCEPT {
|
|
std::swap(__front_cap_, __other.__front_cap_);
|
|
std::swap(__begin_, __other.__begin_);
|
|
std::swap(__cap_, __other.__cap_);
|
|
std::swap(__size_, __other.__size_);
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__split_buffer_size_layout& __other) _NOEXCEPT {
|
|
std::swap(__front_cap_, __other.__front_cap_);
|
|
std::swap(__begin_, __other.__begin_);
|
|
std::swap(__cap_, __other.__cap_);
|
|
std::swap(__size_, __other.__size_);
|
|
std::__swap_allocator(__alloc_, __other.__alloc_);
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __reset() _NOEXCEPT {
|
|
__front_cap_ = nullptr;
|
|
__begin_ = nullptr;
|
|
__size_ = 0;
|
|
__cap_ = 0;
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
|
|
__copy_without_alloc(__split_buffer_size_layout const& __other)
|
|
_NOEXCEPT_(is_nothrow_copy_assignable<pointer>::value) {
|
|
__front_cap_ = __other.__front_cap_;
|
|
__begin_ = __other.__begin_;
|
|
__cap_ = __other.__cap_;
|
|
__size_ = __other.__size_;
|
|
}
|
|
|
|
private:
|
|
pointer __front_cap_ = nullptr;
|
|
pointer __begin_ = nullptr;
|
|
size_type __size_ = 0;
|
|
size_type __cap_ = 0;
|
|
_LIBCPP_NO_UNIQUE_ADDRESS allocator_type __alloc_;
|
|
|
|
template <class, class, class>
|
|
friend class __split_buffer_size_layout;
|
|
};
|
|
|
|
// `__split_buffer` is a contiguous array data structure. It may hold spare capacity at both ends of
|
|
// the sequence. This allows for a `__split_buffer` to grow from both the front and the back without
|
|
// relocating its contents until it runs out of room. This characteristic sets it apart from
|
|
// `std::vector`, which only holds spare capacity at its end. As such, `__split_buffer` is useful
|
|
// for implementing both `std::vector` and `std::deque`.
|
|
//
|
|
// The sequence is stored as a contiguous chunk of memory delimited by the following "pointers" (`o` denotes
|
|
// uninitialized memory and `x` denotes a valid object):
|
|
//
|
|
// |oooooooooooooooooooxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxoooooooooooooooooooooooo|
|
|
// ^ ^ ^ ^
|
|
// __front_cap_ __begin_ __end_ __back_cap_
|
|
//
|
|
// The range [__front_cap_, __begin_) contains uninitialized memory. It is referred to as the "front spare capacity".
|
|
// The range [__begin_, __end_) contains valid objects. It is referred to as the "valid range".
|
|
// The range [__end_, __back_cap_) contains uninitialized memory. It is referred to as the "back spare capacity".
|
|
//
|
|
// The layout of `__split_buffer` is determined by the `_Layout` template template parameter. This
|
|
// `_Layout` allows the above pointers to be stored as different representations, such as integer
|
|
// offsets. A layout class template must provide the following interface:
|
|
//
|
|
// template<class _Tp, class _Allocator, class _Layout>
|
|
// class __layout {
|
|
// protected:
|
|
// using value_type = _Tp;
|
|
// using allocator_type = _Allocator;
|
|
// using __alloc_traits = allocator_traits<allocator_type>;
|
|
// using reference = value_type&;
|
|
// using const_reference = const value_type&;
|
|
// using size_type = typename __alloc_traits::size_type;
|
|
// using difference_type = typename __alloc_traits::difference_type;
|
|
// using pointer = typename __alloc_traits::pointer;
|
|
// using const_pointer = typename __alloc_traits::const_pointer;
|
|
// using iterator = pointer;
|
|
// using const_iterator = const_pointer;
|
|
// using __sentinel_type = /* type that represents the layout's sentinel */;
|
|
//
|
|
// public:
|
|
// __layout() = default;
|
|
// explicit __layout(const allocator_type&);
|
|
//
|
|
// pointer __front_cap();
|
|
// const_pointer __front_cap() const;
|
|
//
|
|
// pointer begin();
|
|
// const_pointer begin() const;
|
|
//
|
|
// pointer end();
|
|
// pointer end() const;
|
|
//
|
|
// size_type size() const;
|
|
// bool empty() const;
|
|
// size_type capacity() const;
|
|
//
|
|
// allocator_type& __get_allocator();
|
|
// allocator_type const& __get_allocator() const;
|
|
//
|
|
// __sentinel_type __raw_sentinel() const;
|
|
// __sentinel_type __raw_capacity() const;
|
|
//
|
|
// void __set_data(pointer);
|
|
// void __set_valid_range(pointer __begin, pointer __end);
|
|
// void __set_valid_range(pointer __begin, size_type __size);
|
|
// void __set_sentinel(pointer __end);
|
|
// void __set_sentinel(size_type __size);
|
|
//
|
|
// void __set_capacity(size_type __capacity);
|
|
// void __set_capacity(pointer __capacity);
|
|
//
|
|
// size_type __front_spare() const;
|
|
// size_type __back_spare() const;
|
|
//
|
|
// reference back();
|
|
// const_reference back() const;
|
|
//
|
|
// template<class _OtherLayout>
|
|
// void __swap_without_allocator(_OtherLayout&);
|
|
// void swap(__layout&);
|
|
//
|
|
// void __reset();
|
|
// void __copy_without_alloc(__layout const&);
|
|
// };
|
|
//
|
|
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
|
|
class __split_buffer : _Layout<__split_buffer<_Tp, _Allocator, _Layout>, _Tp, _Allocator> {
|
|
using __base_type _LIBCPP_NODEBUG = _Layout<__split_buffer<_Tp, _Allocator, _Layout>, _Tp, _Allocator>;
|
|
|
|
public:
|
|
using __base_type::__back_spare;
|
|
using __base_type::__copy_without_alloc;
|
|
using __base_type::__front_cap;
|
|
using __base_type::__front_spare;
|
|
using __base_type::__get_allocator;
|
|
using __base_type::__raw_capacity;
|
|
using __base_type::__raw_sentinel;
|
|
using __base_type::__reset;
|
|
using __base_type::__set_capacity;
|
|
using __base_type::__set_data;
|
|
using __base_type::__set_sentinel;
|
|
using __base_type::__set_valid_range;
|
|
|
|
using typename __base_type::__alloc_traits;
|
|
using typename __base_type::allocator_type;
|
|
using typename __base_type::const_iterator;
|
|
using typename __base_type::const_pointer;
|
|
using typename __base_type::const_reference;
|
|
using typename __base_type::difference_type;
|
|
using typename __base_type::iterator;
|
|
using typename __base_type::pointer;
|
|
using typename __base_type::reference;
|
|
using typename __base_type::size_type;
|
|
using typename __base_type::value_type;
|
|
|
|
// A __split_buffer contains the following members which may be trivially relocatable:
|
|
// - pointer: may be trivially relocatable, so it's checked
|
|
// - allocator_type: may be trivially relocatable, so it's checked
|
|
// __split_buffer doesn't have any self-references, so it's trivially relocatable if its members are.
|
|
using __trivially_relocatable _LIBCPP_NODEBUG = __conditional_t<
|
|
__libcpp_is_trivially_relocatable<pointer>::value && __libcpp_is_trivially_relocatable<allocator_type>::value,
|
|
__split_buffer,
|
|
void>;
|
|
|
|
__split_buffer(const __split_buffer&) = delete;
|
|
__split_buffer& operator=(const __split_buffer&) = delete;
|
|
|
|
_LIBCPP_HIDE_FROM_ABI __split_buffer() = default;
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(allocator_type& __a) : __base_type(__a) {}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit __split_buffer(const allocator_type& __a)
|
|
: __base_type(__a) {}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
|
|
__split_buffer(size_type __cap, size_type __start, allocator_type& __a);
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer(__split_buffer&& __c)
|
|
_NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value);
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer(__split_buffer&& __c, const allocator_type& __a);
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __split_buffer& operator=(__split_buffer&& __c)
|
|
_NOEXCEPT_((__alloc_traits::propagate_on_container_move_assignment::value &&
|
|
is_nothrow_move_assignable<allocator_type>::value) ||
|
|
!__alloc_traits::propagate_on_container_move_assignment::value);
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~__split_buffer();
|
|
|
|
using __base_type::back;
|
|
using __base_type::begin;
|
|
using __base_type::capacity;
|
|
using __base_type::empty;
|
|
using __base_type::end;
|
|
using __base_type::size;
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT { __destruct_at_end(begin()); }
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI reference front() { return *begin(); }
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI const_reference front() const { return *begin(); }
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void shrink_to_fit() _NOEXCEPT;
|
|
|
|
template <class... _Args>
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void emplace_front(_Args&&... __args);
|
|
template <class... _Args>
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void emplace_back(_Args&&... __args);
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_front() { __destruct_at_begin(begin() + 1); }
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void pop_back() { __destruct_at_end(end() - 1); }
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_at_end(size_type __n);
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_at_end(size_type __n, const_reference __x);
|
|
|
|
template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> = 0>
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
|
|
__construct_at_end(_ForwardIterator __first, _ForwardIterator __last);
|
|
|
|
template <class _Iterator, class _Sentinel>
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
|
|
__construct_at_end_with_sentinel(_Iterator __first, _Sentinel __last);
|
|
|
|
template <class _Iterator>
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
|
|
__construct_at_end_with_size(_Iterator __first, size_type __n);
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_begin(pointer __new_begin) {
|
|
__destruct_at_begin(__new_begin, is_trivially_destructible<value_type>());
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_begin(pointer __new_begin, false_type);
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_begin(pointer __new_begin, true_type);
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_end(pointer __new_last) _NOEXCEPT {
|
|
__destruct_at_end(__new_last, false_type());
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_end(pointer __new_last, false_type) _NOEXCEPT;
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_end(pointer __new_last, true_type) _NOEXCEPT;
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void swap(__split_buffer& __x)
|
|
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>);
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __invariants() const {
|
|
if (__front_cap() == nullptr) {
|
|
if (begin() != nullptr)
|
|
return false;
|
|
|
|
if (!empty())
|
|
return false;
|
|
|
|
if (capacity() != 0)
|
|
return false;
|
|
|
|
return true;
|
|
} else {
|
|
if (begin() < __front_cap())
|
|
return false;
|
|
|
|
if (capacity() < size())
|
|
return false;
|
|
|
|
if (end() < begin())
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
|
|
__swap_without_allocator(__split_buffer<value_type, allocator_type, _Layout>& __other) _NOEXCEPT {
|
|
__base_type::__swap_without_allocator(__other);
|
|
}
|
|
|
|
private:
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__split_buffer& __c, true_type)
|
|
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value) {
|
|
__get_allocator() = std::move(__c.__get_allocator());
|
|
}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__split_buffer&, false_type) _NOEXCEPT {}
|
|
|
|
struct _ConstructTransaction {
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20
|
|
_LIBCPP_HIDE_FROM_ABI explicit _ConstructTransaction(__split_buffer* __parent, pointer __p, size_type __n) _NOEXCEPT
|
|
: __pos_(__p),
|
|
__end_(__p + __n),
|
|
__parent_(__parent) {}
|
|
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~_ConstructTransaction() { __parent_->__set_sentinel(__pos_); }
|
|
|
|
pointer __pos_;
|
|
const pointer __end_;
|
|
|
|
private:
|
|
__split_buffer* __parent_;
|
|
};
|
|
|
|
template <class _T2, class _A2, template <class, class, class> class _L2>
|
|
friend class __split_buffer;
|
|
};
|
|
|
|
// Default constructs __n objects starting at `end()`
|
|
// throws if construction throws
|
|
// Precondition: __n > 0
|
|
// Precondition: size() + __n <= capacity()
|
|
// Postcondition: size() == size() + __n
|
|
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::__construct_at_end(size_type __n) {
|
|
_ConstructTransaction __tx(this, end(), __n);
|
|
for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) {
|
|
__alloc_traits::construct(__get_allocator(), std::__to_address(__tx.__pos_));
|
|
}
|
|
}
|
|
|
|
// Copy constructs __n objects starting at `end()` from __x
|
|
// throws if construction throws
|
|
// Precondition: __n > 0
|
|
// Precondition: size() + __n <= capacity()
|
|
// Postcondition: size() == old size() + __n
|
|
// Postcondition: [i] == __x for all i in [size() - __n, __n)
|
|
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
|
|
__split_buffer<_Tp, _Allocator, _Layout>::__construct_at_end(size_type __n, const_reference __x) {
|
|
_ConstructTransaction __tx(this, end(), __n);
|
|
for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_) {
|
|
__alloc_traits::construct(__get_allocator(), std::__to_address(__tx.__pos_), __x);
|
|
}
|
|
}
|
|
|
|
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
|
|
template <class _Iterator, class _Sentinel>
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
|
|
__split_buffer<_Tp, _Allocator, _Layout>::__construct_at_end_with_sentinel(_Iterator __first, _Sentinel __last) {
|
|
allocator_type& __a = __get_allocator();
|
|
for (; __first != __last; ++__first) {
|
|
if (__back_spare() == 0) {
|
|
size_type __old_cap = capacity();
|
|
size_type __new_cap = std::max<size_type>(2 * __old_cap, 8);
|
|
__split_buffer __buf(__new_cap, 0, __a);
|
|
pointer __buf_end = __buf.end();
|
|
pointer __end = end();
|
|
for (pointer __p = begin(); __p != __end; ++__p) {
|
|
__alloc_traits::construct(__buf.__get_allocator(), std::__to_address(__buf_end), std::move(*__p));
|
|
__buf.__set_sentinel(++__buf_end);
|
|
}
|
|
swap(__buf);
|
|
}
|
|
|
|
__alloc_traits::construct(__a, std::__to_address(end()), *__first);
|
|
__set_sentinel(size() + 1);
|
|
}
|
|
}
|
|
|
|
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
|
|
template <class _ForwardIterator, __enable_if_t<__has_forward_iterator_category<_ForwardIterator>::value, int> >
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
|
|
__split_buffer<_Tp, _Allocator, _Layout>::__construct_at_end(_ForwardIterator __first, _ForwardIterator __last) {
|
|
__construct_at_end_with_size(__first, std::distance(__first, __last));
|
|
}
|
|
|
|
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
|
|
template <class _ForwardIterator>
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
|
|
__split_buffer<_Tp, _Allocator, _Layout>::__construct_at_end_with_size(_ForwardIterator __first, size_type __n) {
|
|
_ConstructTransaction __tx(this, end(), __n);
|
|
for (; __tx.__pos_ != __tx.__end_; ++__tx.__pos_, (void)++__first) {
|
|
__alloc_traits::construct(__get_allocator(), std::__to_address(__tx.__pos_), *__first);
|
|
}
|
|
}
|
|
|
|
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline void
|
|
__split_buffer<_Tp, _Allocator, _Layout>::__destruct_at_begin(pointer __new_begin, false_type) {
|
|
pointer __begin = begin();
|
|
// Updating begin at every iteration is unnecessary because destruction can't throw.
|
|
while (__begin != __new_begin)
|
|
__alloc_traits::destroy(__get_allocator(), std::__to_address(__begin++));
|
|
__set_valid_range(__begin, end());
|
|
}
|
|
|
|
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline void
|
|
__split_buffer<_Tp, _Allocator, _Layout>::__destruct_at_begin(pointer __new_begin, true_type) {
|
|
__set_valid_range(__new_begin, end());
|
|
}
|
|
|
|
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI void
|
|
__split_buffer<_Tp, _Allocator, _Layout>::__destruct_at_end(pointer __new_last, false_type) _NOEXCEPT {
|
|
pointer __end = end();
|
|
// Updating begin at every iteration is unnecessary because destruction can't throw.
|
|
while (__new_last != __end)
|
|
__alloc_traits::destroy(__get_allocator(), std::__to_address(--__end));
|
|
__set_sentinel(__end);
|
|
}
|
|
|
|
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20
|
|
__split_buffer<_Tp, _Allocator, _Layout>::__split_buffer(size_type __cap, size_type __start, allocator_type& __a)
|
|
: __base_type(__a) {
|
|
_LIBCPP_ASSERT_INTERNAL(__cap >= __start, "can't have a start point outside the capacity");
|
|
if (__cap > 0) {
|
|
auto __allocation = std::__allocate_at_least(__get_allocator(), __cap);
|
|
__set_data(__allocation.ptr);
|
|
__cap = __allocation.count;
|
|
}
|
|
|
|
pointer __begin = __front_cap() + __start;
|
|
__set_valid_range(__begin, __begin);
|
|
__set_capacity(__cap);
|
|
}
|
|
|
|
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator, _Layout>::~__split_buffer() {
|
|
clear();
|
|
if (__front_cap())
|
|
__alloc_traits::deallocate(__get_allocator(), __front_cap(), capacity());
|
|
}
|
|
|
|
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator, _Layout>::__split_buffer(__split_buffer&& __c)
|
|
_NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
|
|
: __base_type(std::move(__c)) {
|
|
__c.__reset();
|
|
}
|
|
|
|
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20
|
|
__split_buffer<_Tp, _Allocator, _Layout>::__split_buffer(__split_buffer&& __c, const allocator_type& __a)
|
|
: __base_type(__a) {
|
|
if (__a == __c.__get_allocator()) {
|
|
__set_data(__c.__front_cap());
|
|
__set_valid_range(__c.begin(), __c.end());
|
|
__set_capacity(__c.capacity());
|
|
__c.__reset();
|
|
} else {
|
|
auto __allocation = std::__allocate_at_least(__get_allocator(), __c.size());
|
|
__set_data(__allocation.ptr);
|
|
__set_valid_range(__front_cap(), __front_cap());
|
|
__set_capacity(__allocation.count);
|
|
typedef move_iterator<iterator> _Ip;
|
|
__construct_at_end(_Ip(__c.begin()), _Ip(__c.end()));
|
|
}
|
|
}
|
|
|
|
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 __split_buffer<_Tp, _Allocator, _Layout>&
|
|
__split_buffer<_Tp, _Allocator, _Layout>::operator=(__split_buffer&& __c)
|
|
_NOEXCEPT_((__alloc_traits::propagate_on_container_move_assignment::value &&
|
|
is_nothrow_move_assignable<allocator_type>::value) ||
|
|
!__alloc_traits::propagate_on_container_move_assignment::value) {
|
|
clear();
|
|
shrink_to_fit();
|
|
__copy_without_alloc(__c);
|
|
__move_assign_alloc(__c, integral_constant<bool, __alloc_traits::propagate_on_container_move_assignment::value>());
|
|
__c.__reset();
|
|
return *this;
|
|
}
|
|
|
|
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::swap(__split_buffer& __x)
|
|
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>) {
|
|
__base_type::swap(__x);
|
|
}
|
|
|
|
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::shrink_to_fit() _NOEXCEPT {
|
|
if (capacity() > size()) {
|
|
#if _LIBCPP_HAS_EXCEPTIONS
|
|
try {
|
|
#endif // _LIBCPP_HAS_EXCEPTIONS
|
|
__split_buffer<value_type, allocator_type, _Layout> __t(size(), 0, __get_allocator());
|
|
if (__t.capacity() < capacity()) {
|
|
__t.__construct_at_end(move_iterator<pointer>(begin()), move_iterator<pointer>(end()));
|
|
__t.__set_sentinel(size());
|
|
__swap_without_allocator(__t);
|
|
}
|
|
#if _LIBCPP_HAS_EXCEPTIONS
|
|
} catch (...) {
|
|
}
|
|
#endif // _LIBCPP_HAS_EXCEPTIONS
|
|
}
|
|
}
|
|
|
|
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
|
|
template <class... _Args>
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::emplace_front(_Args&&... __args) {
|
|
if (__front_spare() == 0) {
|
|
pointer __end = end();
|
|
if (__back_spare() > 0) {
|
|
// The elements are pressed up against the front of the buffer: we need to move them back a
|
|
// little bit to make `emplace_front` have amortised O(1) complexity.
|
|
difference_type __d = __back_spare();
|
|
__d = (__d + 1) / 2;
|
|
auto __new_end = __end + __d;
|
|
__set_valid_range(std::move_backward(begin(), __end, __new_end), __new_end);
|
|
} else {
|
|
size_type __c = std::max<size_type>(2 * capacity(), 1);
|
|
__split_buffer<value_type, allocator_type, _Layout> __t(__c, (__c + 3) / 4, __get_allocator());
|
|
__t.__construct_at_end(move_iterator<pointer>(begin()), move_iterator<pointer>(__end));
|
|
__base_type::__swap_without_allocator(__t);
|
|
}
|
|
}
|
|
|
|
__alloc_traits::construct(__get_allocator(), std::__to_address(begin() - 1), std::forward<_Args>(__args)...);
|
|
__set_valid_range(begin() - 1, size() + 1);
|
|
}
|
|
|
|
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
|
|
template <class... _Args>
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 void __split_buffer<_Tp, _Allocator, _Layout>::emplace_back(_Args&&... __args) {
|
|
pointer __end = end();
|
|
if (__back_spare() == 0) {
|
|
if (__front_spare() > 0) {
|
|
difference_type __d = __front_spare();
|
|
__d = (__d + 1) / 2;
|
|
__end = std::move(begin(), __end, begin() - __d);
|
|
__set_valid_range(begin() - __d, __end);
|
|
} else {
|
|
size_type __c = std::max<size_type>(2 * capacity(), 1);
|
|
__split_buffer<value_type, allocator_type, _Layout> __t(__c, __c / 4, __get_allocator());
|
|
__t.__construct_at_end(move_iterator<pointer>(begin()), move_iterator<pointer>(__end));
|
|
__base_type::__swap_without_allocator(__t);
|
|
}
|
|
}
|
|
|
|
__alloc_traits::construct(__get_allocator(), std::__to_address(__end), std::forward<_Args>(__args)...);
|
|
__set_sentinel(++__end);
|
|
}
|
|
|
|
template <class _Tp, class _Allocator, template <class, class, class> class _Layout>
|
|
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI void
|
|
swap(__split_buffer<_Tp, _Allocator, _Layout>& __x, __split_buffer<_Tp, _Allocator, _Layout>& __y)
|
|
_NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) {
|
|
__x.swap(__y);
|
|
}
|
|
|
|
_LIBCPP_END_NAMESPACE_STD
|
|
|
|
_LIBCPP_POP_MACROS
|
|
|
|
#endif // _LIBCPP___SPLIT_BUFFER
|