5#ifndef INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_INLINE_CONTAINER_DEQUE_HPP_
6#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_INLINE_CONTAINER_DEQUE_HPP_
8#include "arene/base/algorithm/copy.hpp"
9#include "arene/base/algorithm/rotate.hpp"
10#include "arene/base/array/array.hpp"
11#include "arene/base/constraints/constraints.hpp"
12#include "arene/base/contracts/contract.hpp"
13#include "arene/base/inline_container/detail/iterator_interface.hpp"
14#include "arene/base/inline_container/detail/range_interface.hpp"
15#include "arene/base/inline_container/detail/try_construct_interface.hpp"
16#include "arene/base/inline_container/detail/unsafe_element_storage.hpp"
17#include "arene/base/iterator/distance.hpp"
18#include "arene/base/iterator/next.hpp"
19#include "arene/base/memory/construct_at.hpp"
20#include "arene/base/stdlib_choice/cstddef.hpp"
21#include "arene/base/stdlib_choice/declval.hpp"
22#include "arene/base/stdlib_choice/enable_if.hpp"
23#include "arene/base/stdlib_choice/forward.hpp"
24#include "arene/base/stdlib_choice/ignore.hpp"
25#include "arene/base/stdlib_choice/initializer_list.hpp"
26#include "arene/base/stdlib_choice/integral_constant.hpp"
27#include "arene/base/stdlib_choice/is_constructible.hpp"
28#include "arene/base/stdlib_choice/is_copy_assignable.hpp"
29#include "arene/base/stdlib_choice/is_copy_constructible.hpp"
30#include "arene/base/stdlib_choice/is_default_constructible.hpp"
31#include "arene/base/stdlib_choice/is_move_assignable.hpp"
32#include "arene/base/stdlib_choice/is_move_constructible.hpp"
33#include "arene/base/stdlib_choice/is_same.hpp"
34#include "arene/base/stdlib_choice/is_trivially_copyable.hpp"
35#include "arene/base/stdlib_choice/iterator_tags.hpp"
36#include "arene/base/stdlib_choice/iterator_traits.hpp"
37#include "arene/base/stdlib_choice/min_value_overload.hpp"
38#include "arene/base/stdlib_choice/move.hpp"
39#include "arene/base/stdlib_choice/numeric_limits.hpp"
40#include "arene/base/type_manipulation/non_constructible_dummy.hpp"
41#include "arene/base/type_traits/conditional.hpp"
42#include "arene/base/type_traits/iterator_category_traits.hpp"
43#include "arene/base/utility/safe_comparisons.hpp"
50namespace inline_deque_detail {
59constexpr auto constrained_modulo(T value, T modulus)
noexcept -> T {
60 return value < modulus ? value : value - modulus;
69constexpr auto next_at_front_impl(std::size_t
const current_front, std::size_t
const capacity)
noexcept -> std::size_t {
70 return current_front > 0U ? current_front - 1U : capacity - 1U;
75struct physical_indices {
77 static constexpr std::size_t logical_end{std::numeric_limits<std::size_t>::max()};
92template <std::size_t Capacity,
bool AllowWrapping>
93class ring_buffer_indices {
96 using size_type = std::size_t;
100 static constexpr std::integral_constant<size_type, Capacity> capacity{};
105 constexpr auto back_index()
const noexcept -> size_type {
return n_from_front(size() - 1U); }
111 constexpr auto n_from_back(size_type offset)
const noexcept -> size_type {
112 return n_from_front(size() - 1U - offset);
117 constexpr auto front_index()
const noexcept -> size_type {
return front_; }
123 constexpr auto n_from_front(size_type offset)
const noexcept -> size_type {
124 return constrained_modulo(front_index() + offset, capacity());
129 constexpr auto next_at_front()
const noexcept -> size_type {
return next_at_front_impl(front_index(), capacity()); }
133 constexpr auto next_at_back()
const noexcept -> size_type {
return n_from_front(size()); }
137 constexpr auto size()
const noexcept -> size_type {
return size_; }
141 constexpr auto empty()
const noexcept ->
bool {
return size() == 0U; }
145 constexpr void shrink_at_front(size_type amount = 1U)
noexcept {
146 front_ = n_from_front(amount);
151 constexpr void shrink_at_back()
noexcept { --size_; }
154 constexpr void grow_at_front()
noexcept {
155 front_ = next_at_front();
161 constexpr void grow_at_back(size_type amount = 1U)
noexcept { size_ += amount; }
167 constexpr auto get_physical_indices(std::size_t current_index)
const noexcept -> physical_indices {
168 return {current_index, front_index(), back_index(), capacity()};
173 size_type front_{0U};
178template <std::size_t Capacity,
bool AllowWrapping>
179constexpr std::integral_constant<
typename ring_buffer_indices<Capacity, AllowWrapping>::size_type, Capacity>
180 ring_buffer_indices<Capacity, AllowWrapping>::capacity;
186template <
typename Derived,
bool AllowWrapping>
187class storage_wrapping_interface {
190 constexpr auto derived()
noexcept -> Derived& {
return static_cast<Derived&>(*
this); }
196 constexpr auto ensure_space_at_back()
noexcept ->
void {
197 if (derived().size() == Derived::capacity()) {
198 using value_type =
typename Derived::value_type;
204 derived().at_buffer_idx(derived().front_index()).~value_type();
205 derived().shrink_at_front();
215 constexpr auto ensure_space_at_front()
noexcept ->
void {
216 if (derived().size() == Derived::capacity()) {
217 using value_type =
typename Derived::value_type;
223 derived().at_buffer_idx(derived().back_index()).~value_type();
224 derived().shrink_at_back();
235template <
typename Derived>
236class storage_wrapping_interface<Derived,
false> {
239 constexpr auto derived()
const noexcept -> Derived
const& {
return static_cast<Derived
const&>(*
this); }
245 constexpr auto ensure_space_at_back()
const noexcept ->
void {
246 ARENE_PRECONDITION(derived().size() < Derived::capacity());
252 constexpr auto ensure_space_at_front()
const noexcept ->
void {
253 ARENE_PRECONDITION(derived().size() < Derived::capacity());
270 std::size_t Capacity,
272 bool = std::is_trivially_default_constructible<T>::value && std::is_trivially_copyable<T>::value>
274class inline_deque_internal_storage
275 :
private array<inline_container::detail::unsafe_element_storage<T>, Capacity>
276 ,
private ring_buffer_indices<Capacity, AllowWrapping>
277 ,
protected storage_wrapping_interface<inline_deque_internal_storage<T, Capacity, AllowWrapping>, AllowWrapping> {
281 friend storage_wrapping_interface<inline_deque_internal_storage, AllowWrapping>;
285 using size_type =
typename ring_buffer_indices<Capacity, AllowWrapping>::size_type;
287 using value_type = T;
289 using reference = value_type&;
291 using const_reference = value_type
const&;
295 static constexpr std::integral_constant<size_type, Capacity> capacity{};
300 using ring_buffer_indices<Capacity, AllowWrapping>::size;
304 using ring_buffer_indices<Capacity, AllowWrapping>::empty;
307 using ring_buffer_indices<Capacity, AllowWrapping>::front_index;
310 using ring_buffer_indices<Capacity, AllowWrapping>::back_index;
313 using ring_buffer_indices<Capacity, AllowWrapping>::n_from_front;
316 using ring_buffer_indices<Capacity, AllowWrapping>::n_from_back;
319 using ring_buffer_indices<Capacity, AllowWrapping>::get_physical_indices;
323 using element_storage = inline_container::detail::unsafe_element_storage<T>;
327 static_assert(
alignof(element_storage) ==
alignof(T),
"Alignment must be the same");
329 static_assert(
sizeof(element_storage) ==
sizeof(T),
"Size must be the same");
334 using copy_constructor_arg =
335 conditional_t<std::is_copy_constructible<T>::value, inline_deque_internal_storage, non_constructible_dummy>;
340 using copy_assignment_arg = conditional_t<
341 std::is_copy_constructible<T>::value && std::is_copy_assignable<T>::value,
342 inline_deque_internal_storage,
343 non_constructible_dummy>;
348 using move_constructor_arg =
349 conditional_t<std::is_move_constructible<T>::value, inline_deque_internal_storage, non_constructible_dummy>;
354 using move_assignment_arg = conditional_t<
355 std::is_move_constructible<T>::value && std::is_move_assignable<T>::value,
356 inline_deque_internal_storage,
357 non_constructible_dummy>;
361 constexpr inline_deque_internal_storage() =
default;
368 template <
typename Iterator>
369 constexpr inline_deque_internal_storage(Iterator in_begin, Iterator in_end)
noexcept(
370 noexcept(::arene::base::distance(in_begin, in_end)) &&
371 std::is_nothrow_constructible<T,
typename std::iterator_traits<Iterator>::reference>::value
373 : ::arene::base::array<element_storage, Capacity>{} {
374 typename std::iterator_traits<Iterator>::difference_type
const distance{::arene::base::distance(in_begin, in_end)};
375 ARENE_PRECONDITION(distance >= 0);
376 ARENE_PRECONDITION(
static_cast<size_type>(distance) <= capacity);
378 while (in_begin != in_end) {
379 std::ignore = emplace_back(*in_begin);
391 constexpr inline_deque_internal_storage(copy_constructor_arg
const& other
392 )
noexcept(std::is_nothrow_copy_constructible<T>::value) {
393 for (inline_deque_internal_storage::size_type i{}; i < other.size(); i++) {
394 std::ignore = emplace_front(other[other.n_from_back(i)].object);
404 constexpr inline_deque_internal_storage(move_constructor_arg&& other
405 )
noexcept(std::is_nothrow_move_constructible<T>::value) {
406 for (inline_deque_internal_storage::size_type i{}; i < other.size(); i++) {
407 std::ignore = emplace_front(std::move(other[other.n_from_back(i)].object));
420 constexpr auto operator=(copy_assignment_arg
const& other
421 )
noexcept(std::is_nothrow_copy_constructible<T>::value && std::is_nothrow_copy_assignable<T>::value)
422 -> inline_deque_internal_storage& {
423 if (&other !=
this) {
425 while (
this->size() > other.size()) {
430 inline_deque_internal_storage::size_type assignments{std::min(
this->size(), other.size())};
431 for (inline_deque_internal_storage::size_type i{}; i < assignments; ++i) {
432 (*
this)[
this->n_from_back(i)].object = other[other.n_from_back(i)].object;
436 if (
this->size() < other.size()) {
437 size_type
const pushes{other.size() -
this->size()};
438 for (inline_deque_internal_storage::size_type i{}; i < pushes; ++i) {
439 std::ignore = emplace_front(other[other.n_from_back(assignments + i)].object);
454 constexpr auto operator=(move_assignment_arg&& other
455 )
noexcept(std::is_nothrow_move_constructible<T>::value && std::is_nothrow_move_assignable<T>::value)
456 -> inline_deque_internal_storage& {
457 if (&other !=
this) {
458 size_type
const target_size{other.size()};
461 while (
this->size() > target_size) {
466 for (inline_deque_internal_storage::size_type i{}; i <
this->size(); ++i) {
467 (*
this)[
this->n_from_back(i)].object = std::move(other[other.back_index()].object);
472 while (
this->size() < target_size) {
473 std::ignore = emplace_front(std::move(other[other.back_index()].object));
487 ~inline_deque_internal_storage() { clear(); }
499 template <
typename... Args>
500 constexpr auto emplace_front(Args&&... args)
noexcept(std::is_nothrow_constructible<T, Args...>::value) -> T& {
501 this->ensure_space_at_front();
502 T& new_ref{*construct_at(&(*
this)[
this->next_at_front()].object, std::forward<Args>(args)...)};
503 this->grow_at_front();
514 template <
typename... Args>
515 constexpr auto emplace_back(Args&&... args)
noexcept(std::is_nothrow_constructible<T, Args...>::value) -> T& {
516 this->ensure_space_at_back();
517 T& new_ref{*construct_at(&(*
this)[
this->next_at_back()].object, std::forward<Args>(args)...)};
518 this->grow_at_back();
527 constexpr void pop_front()
noexcept {
528 ARENE_PRECONDITION(
this->size() > size_type{});
529 (*
this)[
this->front_index()].object.~T();
530 this->shrink_at_front();
535 constexpr void pop_back()
noexcept {
536 ARENE_PRECONDITION(
this->size() > size_type{});
537 (*
this)[
this->back_index()].object.~T();
538 this->shrink_at_back();
544 constexpr auto at_buffer_idx(std::size_t buffer_idx)
const noexcept -> const_reference {
545 return (*
this)[buffer_idx].object;
551 constexpr auto at_buffer_idx(std::size_t buffer_idx)
noexcept -> reference {
return (*
this)[buffer_idx].object; }
555 constexpr void clear()
noexcept {
556 while (!
this->empty()) {
574template <
typename T, std::size_t Capacity,
bool AllowWrapping>
575class inline_deque_internal_storage<T, Capacity, AllowWrapping,
true>
576 :
private array<T, Capacity>
577 ,
private ring_buffer_indices<Capacity, AllowWrapping>
578 ,
protected storage_wrapping_interface<inline_deque_internal_storage<T, Capacity, AllowWrapping>, AllowWrapping> {
582 friend storage_wrapping_interface<inline_deque_internal_storage, AllowWrapping>;
586 using size_type =
typename ring_buffer_indices<Capacity, AllowWrapping>::size_type;
588 using value_type = T;
590 using reference = value_type&;
592 using const_reference = value_type
const&;
596 static constexpr std::integral_constant<size_type, Capacity> capacity{};
601 using ring_buffer_indices<Capacity, AllowWrapping>::size;
605 using ring_buffer_indices<Capacity, AllowWrapping>::empty;
608 using ring_buffer_indices<Capacity, AllowWrapping>::front_index;
611 using ring_buffer_indices<Capacity, AllowWrapping>::back_index;
614 using ring_buffer_indices<Capacity, AllowWrapping>::n_from_front;
617 using ring_buffer_indices<Capacity, AllowWrapping>::n_from_back;
620 using ring_buffer_indices<Capacity, AllowWrapping>::get_physical_indices;
624 constexpr inline_deque_internal_storage()
noexcept
625 : array<T, Capacity>{},
626 ring_buffer_indices<Capacity, AllowWrapping>{},
627 storage_wrapping_interface<inline_deque_internal_storage, AllowWrapping>{} {}
635 template <
typename Iterator>
636 constexpr inline_deque_internal_storage(Iterator in_begin, Iterator in_end)
noexcept(
noexcept(
637 ::arene::base::distance(in_begin, in_end)
638 ) &&
noexcept(::arene::base::copy(in_begin, in_end, std::declval<array<T, Capacity>&>().begin())))
639 : ::arene::base::array<T, Capacity>{} {
640 auto const count = ::arene::base::distance(in_begin, in_end);
641 ARENE_PRECONDITION((count >= 0) && (
static_cast<std::size_t>(count) <= capacity()));
643 typename ::arene::base::array<T, Capacity>::iterator
const new_end{
644 ::arene::base::copy(in_begin, in_end,
this->begin())
648 this->grow_at_back(
static_cast<std::size_t>(::arene::base::distance(
this->begin(), new_end)));
658 template <
typename... Args>
659 constexpr auto emplace_front(Args&&... args)
noexcept(std::is_nothrow_constructible<T, Args...>::value) -> T& {
660 this->ensure_space_at_front();
663 T& new_ref{((*
this)[
this->next_at_front()] = T(std::forward<Args>(args)...))};
666 this->grow_at_front();
677 template <
typename... Args>
678 constexpr auto emplace_back(Args&&... args)
noexcept(std::is_nothrow_constructible<T, Args...>::value) -> T& {
679 this->ensure_space_at_back();
682 T& new_ref{((*
this)[
this->next_at_back()] = T(std::forward<Args>(args)...))};
685 this->grow_at_back();
691 constexpr void pop_front()
noexcept {
692 ARENE_PRECONDITION(
this->size() > size_type{});
693 this->shrink_at_front();
698 constexpr void pop_back()
noexcept {
699 ARENE_PRECONDITION(
this->size() > size_type{});
700 this->shrink_at_back();
706 constexpr auto at_buffer_idx(std::size_t buffer_idx)
const noexcept -> const_reference {
return (*
this)[buffer_idx]; }
711 constexpr auto at_buffer_idx(std::size_t buffer_idx)
noexcept -> reference {
return (*
this)[buffer_idx]; }
715template <
typename T, std::size_t Capacity,
bool AllowWrapping,
bool IsTrivial>
716constexpr std::integral_constant<
717 typename inline_deque_internal_storage<T, Capacity, AllowWrapping, IsTrivial>::size_type,
719 inline_deque_internal_storage<T, Capacity, AllowWrapping, IsTrivial>::capacity;
721template <
typename T, std::size_t Capacity,
bool AllowWrapping>
723 integral_constant<
typename inline_deque_internal_storage<T, Capacity, AllowWrapping,
true>::size_type, Capacity>
724 inline_deque_internal_storage<T, Capacity, AllowWrapping,
true>::capacity;
732constexpr auto step_logical_index_forward(physical_indices
const& indices)
noexcept -> std::size_t {
734 if (indices.current == indices.back) {
735 return indices.logical_end;
739 if (indices.current == indices.capacity - 1U) {
740 return std::size_t{};
744 return indices.current + 1U;
751constexpr auto step_logical_index_backward(physical_indices
const& indices)
noexcept -> std::size_t {
753 if (indices.current == indices.logical_end) {
758 if (indices.current == std::size_t{}) {
759 return indices.capacity - 1U;
763 return indices.current - 1U;
770constexpr auto get_logical_index_impl(physical_indices
const& indices)
noexcept -> std::ptrdiff_t {
771 std::size_t
const shifted_idx{
772 indices.front <= indices.current ? indices.current : indices.current + indices.capacity
774 return static_cast<std::ptrdiff_t>(shifted_idx) -
static_cast<std::ptrdiff_t>(indices.front);
780template <
class T, std::size_t Capacity>
781class inline_deque_try_construct_policy {
784 using size_type = std::size_t;
786 using value_type = T;
789 static constexpr auto capacity_of()
noexcept -> size_type {
return Capacity; }
801template <
typename T, std::size_t Capacity,
bool AllowWrapping>
802class inline_deque_impl
803 :
private inline_deque_detail::inline_deque_internal_storage<T, Capacity, AllowWrapping>
804 ,
public inline_container::detail::range_interface<inline_deque_impl<T, Capacity, AllowWrapping>> {
807 using storage_type = inline_deque_detail::inline_deque_internal_storage<T, Capacity, AllowWrapping>;
810 using range_interface = inline_container::detail::range_interface<inline_deque_impl>;
817 template <
bool IsConst>
818 class cyclical_iterator :
public inline_container_detail::iterator_interface<cyclical_iterator<IsConst>> {
821 using iterator_interface = inline_container_detail::iterator_interface<cyclical_iterator<IsConst>>;
825 friend cyclical_iterator<
true>;
831 using value_type = T;
833 using pointer = conditional_t<IsConst, T
const*, T*>;
835 using reference =
decltype(*std::declval<pointer>());
837 using difference_type =
decltype(std::declval<pointer>() - std::declval<pointer>());
839 using iterator_category = std::random_access_iterator_tag;
846 Capacity <= std::numeric_limits<std::size_t>::max(),
847 "inline_deque capacity() + 1U must be representable using the type of capacity()"
850 cmp_less_equal(Capacity + 1U, std::numeric_limits<difference_type>::max()),
851 "inline_deque capacity must be expressable as its iterator's difference_type"
859 static constexpr std::integral_constant<std::size_t, std::numeric_limits<std::size_t>::max()> end_index{};
867 constexpr cyclical_iterator()
noexcept
868 : iterator_interface(),
875 constexpr cyclical_iterator(
876 conditional_t<IsConst, inline_deque_impl
const&, inline_deque_impl&> deque,
879 : iterator_interface(),
886 template <
bool Enable = IsConst, constraints<std::enable_if_t<Enable>> =
nullptr>
888 constexpr cyclical_iterator(cyclical_iterator<!Enable> non_const)
noexcept
889 : iterator_interface(),
890 deque_(non_const.deque_),
891 idx_(non_const.idx_) {}
898 constexpr auto operator*()
const noexcept -> reference {
901 ARENE_PRECONDITION(idx_ != end_index);
902 return deque_->at_buffer_idx(idx_);
911 constexpr auto operator+=(difference_type diff)
noexcept -> cyclical_iterator& {
914 set_logical_index(get_logical_index() + diff);
927 friend constexpr auto operator-(cyclical_iterator
const& lhs, cyclical_iterator
const& rhs)
noexcept
929 ARENE_PRECONDITION(lhs.deque_ == rhs.deque_);
933 difference_type
const logical_lhs_idx{lhs.get_logical_index()};
934 difference_type
const logical_rhs_idx{rhs.get_logical_index()};
936 return logical_lhs_idx - logical_rhs_idx;
946 friend constexpr auto operator==(cyclical_iterator
const& lhs, cyclical_iterator
const& rhs)
noexcept ->
bool {
947 return (lhs.deque_ == rhs.deque_) && (lhs.idx_ == rhs.idx_);
955 constexpr auto physical_index()
const noexcept -> std::size_t {
return idx_; }
960 constexpr auto logical_space_size()
const noexcept -> difference_type {
961 return static_cast<difference_type>(deque_->size() + 1U);
966 constexpr auto get_logical_index()
const noexcept -> difference_type {
967 if (idx_ == end_index()) {
968 ARENE_PRECONDITION(deque_ !=
nullptr);
969 return static_cast<difference_type>(deque_->size());
974 return inline_deque_detail::get_logical_index_impl(deque_->get_physical_indices(idx_));
981 constexpr auto set_logical_index(difference_type logical_idx)
noexcept ->
void {
982 if (logical_idx + 1 == logical_space_size()) {
985 idx_ = inline_deque_detail::constrained_modulo(
986 deque_->front_index() +
static_cast<std::size_t>(logical_idx),
997 constexpr auto do_step_forward()
noexcept ->
void {
998 idx_ = inline_deque_detail::step_logical_index_forward(deque_->get_physical_indices(idx_));
1006 constexpr auto do_step_backward()
noexcept ->
void {
1007 idx_ = inline_deque_detail::step_logical_index_backward(deque_->get_physical_indices(idx_));
1024 friend constexpr auto
1025 step_forward(inline_container_detail::iterator_interface_tag, cyclical_iterator& self)
noexcept ->
void {
1026 self.do_step_forward();
1035 friend constexpr auto
1036 step_backward(inline_container_detail::iterator_interface_tag, cyclical_iterator& self)
noexcept ->
void {
1037 self.do_step_backward();
1048 conditional_t<IsConst, inline_deque_impl
const*, inline_deque_impl*> deque_;
1058 using size_type =
typename storage_type::size_type;
1060 using value_type = T;
1063 using reference = value_type&;
1065 using const_reference = value_type
const&;
1067 using iterator = cyclical_iterator<
false>;
1069 using const_iterator = cyclical_iterator<
true>;
1073 static constexpr std::integral_constant<size_type, Capacity> capacity{};
1076 static constexpr std::integral_constant<
bool, AllowWrapping> wrapping_allowed{};
1081 constexpr inline_deque_impl()
noexcept
1083 range_interface(
this) {}
1095 std::enable_if_t<arene::base::is_forward_iterator_v<Iterator>>,
1097 std::is_constructible<value_type,
typename std::iterator_traits<Iterator>::reference>::value>> =
nullptr>
1098 constexpr inline_deque_impl(Iterator in_begin, Iterator in_end)
noexcept(
1099 noexcept(::arene::base::distance(in_begin, in_end)) &&
1100 std::is_nothrow_constructible<value_type,
typename std::iterator_traits<Iterator>::reference>::value
1102 : storage_type(in_begin, in_end),
1103 range_interface(
this) {}
1106 using storage_type::empty;
1111 constexpr auto begin()
const noexcept -> const_iterator {
1112 if (
this->empty()) {
1115 return {*
this,
this->front_index()};
1120 constexpr auto begin()
noexcept -> iterator {
1121 if (
this->empty()) {
1124 return {*
this,
this->front_index()};
1129 constexpr auto end()
const noexcept -> const_iterator {
return {*
this, const_iterator::end_index}; }
1133 constexpr auto end()
noexcept -> iterator {
return {*
this, iterator::end_index}; }
1140 using range_interface::cbegin;
1142 using range_interface::cend;
1145 using range_interface::rbegin;
1147 using range_interface::rend;
1150 using range_interface::crbegin;
1152 using range_interface::crend;
1155 using range_interface::front;
1157 using range_interface::back;
1159 using range_interface::operator[];
1163 using storage_type::size;
1168 using storage_type::emplace_front;
1173 using storage_type::emplace_back;
1180 constexpr auto push_front(value_type
const& arg)
noexcept(std::is_nothrow_copy_constructible<value_type>::value)
1182 std::ignore =
this->emplace_front(arg);
1190 constexpr auto push_front(value_type&& arg)
noexcept(std::is_nothrow_move_constructible<value_type>::value) ->
void {
1191 std::ignore =
this->emplace_front(std::move(arg));
1199 constexpr auto push_back(value_type
const& arg)
noexcept(std::is_nothrow_copy_constructible<value_type>::value)
1201 std::ignore =
this->emplace_back(arg);
1209 constexpr auto push_back(value_type&& arg)
noexcept(std::is_nothrow_move_constructible<value_type>::value) ->
void {
1210 std::ignore =
this->emplace_back(std::move(arg));
1222 template <
typename U,
bool Wrap = wrapping_allowed, constraints<std::enable_if_t<Wrap>> =
nullptr>
1223 constexpr auto internal_insert_at_front(U&& value)
noexcept(std::is_nothrow_constructible<value_type, U&&>::value)
1224 -> inline_deque_impl::iterator {
1225 if (
this->size() <
this->capacity()) {
1226 std::ignore =
this->emplace_front(std::forward<U>(value));
1229 return this->begin();
1240 template <
typename U,
bool Wrap = wrapping_allowed, constraints<std::enable_if_t<!Wrap>> =
nullptr>
1241 constexpr auto internal_insert_at_front(U&& value)
noexcept(std::is_nothrow_constructible<value_type, U&&>::value)
1242 -> inline_deque_impl::iterator {
1243 std::ignore =
this->emplace_front(std::forward<U>(value));
1244 return this->begin();
1252 template <
typename U>
1253 constexpr auto internal_insert_at_back(U&& value)
noexcept(std::is_nothrow_constructible<value_type, U&&>::value)
1254 -> inline_deque_impl::iterator {
1256 std::ignore =
this->emplace_back(std::forward<U>(value));
1257 return inline_deque_impl::iterator(*
this,
this->back_index());
1268 template <
typename U>
1269 constexpr auto internal_insert_in_middle(inline_deque_impl::const_iterator pos, U&& value)
noexcept(
1270 std::is_nothrow_constructible<value_type, U&&>::value && std::is_nothrow_move_assignable<value_type>::value &&
1271 std::is_nothrow_move_constructible<value_type>::value
1272 ) -> inline_deque_impl::iterator {
1274 this->ensure_space_at_back();
1277 auto mutable_pos = inline_deque_impl::iterator(*
this, pos.physical_index());
1278 inline_deque_impl::iterator insertion_target;
1284 if (
static_cast<size_type>(distance(
this->cbegin(), pos)) < (
this->capacity() / 2U)) {
1286 std::ignore =
this->emplace_front(std::forward<U>(value));
1288 insertion_target = rotate(
this->begin(), next(
this->begin()), mutable_pos);
1291 std::ignore =
this->emplace_back(std::forward<U>(value));
1293 std::ignore = rotate(mutable_pos, inline_deque_impl::iterator(*
this,
this->back_index()),
this->end());
1294 insertion_target = mutable_pos;
1299 return insertion_target;
1313 template <
typename U>
1314 constexpr auto internal_insert(inline_deque_impl::const_iterator pos, U&& value)
noexcept(
noexcept(
1315 std::declval<inline_deque_impl>().internal_insert_at_front(std::forward<U>(value))
1316 ) &&
noexcept(std::declval<inline_deque_impl>().internal_insert_at_back(std::forward<U>(value))
1317 ) &&
noexcept(std::declval<inline_deque_impl>().internal_insert_in_middle(pos, std::forward<U>(value))))
1318 -> inline_deque_impl::iterator {
1319 if (pos ==
this->cbegin()) {
1320 return internal_insert_at_front(std::forward<U>(value));
1322 if (pos ==
this->cend()) {
1323 return internal_insert_at_back(std::forward<U>(value));
1326 return internal_insert_in_middle(pos, std::forward<U>(value));
1343 typename U = value_type,
1345 std::enable_if_t<std::is_same<U, value_type>::value>,
1346 std::enable_if_t<std::is_copy_assignable<U>::value>,
1347 std::enable_if_t<std::is_move_assignable<U>::value>,
1348 std::enable_if_t<std::is_move_constructible<U>::value>> =
nullptr>
1349 constexpr auto insert(inline_deque_impl::const_iterator pos, value_type
const& value)
noexcept(
1350 noexcept(std::declval<inline_deque_impl>().internal_insert(pos, value))
1351 ) -> inline_deque_impl::iterator {
1352 return this->internal_insert(pos, value);
1368 typename U = value_type,
1370 std::enable_if_t<std::is_same<U, value_type>::value>,
1371 std::enable_if_t<std::is_move_assignable<U>::value>,
1372 std::enable_if_t<std::is_move_constructible<U>::value>> =
nullptr>
1373 constexpr auto insert(inline_deque_impl::const_iterator pos, value_type&& value)
noexcept(
1374 noexcept(std::declval<inline_deque_impl>().internal_insert(pos, std::move(value)))
1375 ) -> inline_deque_impl::iterator {
1376 return this->internal_insert(pos, std::move(value));
1381 using storage_type::pop_front;
1385 using storage_type::pop_back;
1389template <
typename T, std::size_t Capacity,
bool AllowWrapping>
1390constexpr std::integral_constant<
typename inline_deque_impl<T, Capacity, AllowWrapping>::size_type, Capacity>
1391 inline_deque_impl<T, Capacity, AllowWrapping>::capacity;
1393template <
typename T, std::size_t Capacity,
bool AllowWrapping>
1394constexpr std::integral_constant<
bool, AllowWrapping> inline_deque_impl<T, Capacity, AllowWrapping>::wrapping_allowed;
1396template <
typename T, std::size_t Capacity,
bool AllowWrapping>
1397template <
bool IsConst>
1398constexpr std::integral_constant<std::size_t, std::numeric_limits<std::size_t>::max()>
1399 inline_deque_impl<T, Capacity, AllowWrapping>::cyclical_iterator<IsConst>::end_index;
1410template <
typename T, std::size_t Capacity>
1412 :
private inline_deque_detail::inline_deque_impl<T, Capacity,
false>
1417 using impl = inline_deque_detail::inline_deque_impl<T, Capacity,
false>;
1426 using typename impl::const_iterator;
1428 using typename impl::const_reference;
1430 using typename impl::iterator;
1432 using typename impl::reference;
1434 using typename impl::size_type;
1436 using typename impl::value_type;
1439 using impl::wrapping_allowed;
1489 using impl::crbegin;
1504 using impl::operator[];
1507 using impl::emplace_back;
1509 using impl::emplace_front;
1511 using impl::pop_back;
1513 using impl::pop_front;
1515 using impl::push_back;
1517 using impl::push_front;
A container with fixed capacity featuring constant time insertion and removal at opposite ends; i....
Definition deque.hpp:1415
constexpr inline_deque() noexcept
Construct an empty queue.
Definition deque.hpp:1443
Definition array_exceptions_disabled.cpp:11
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10