Iros
 
Loading...
Searching...
No Matches
linked_list.h
Go to the documentation of this file.
1#pragma once
2
15#include "di/platform/prelude.h"
16#include "di/util/exchange.h"
20
21namespace di::container {
22namespace detail {
23 template<typename T>
24 struct LinkedListTag;
25
26 template<typename T>
27 struct LinkedListNode : IntrusiveListNode<LinkedListTag<T>> {
28 public:
29 template<typename... Args>
30 requires(concepts::ConstructibleFrom<T, Args...>)
31 constexpr LinkedListNode(InPlace, Args&&... args) : m_value(util::forward<Args>(args)...) {}
32
33 constexpr auto value() -> T& { return m_value; }
34
35 private:
36 T m_value;
37 };
38
39 template<typename T>
40 struct LinkedListTag : IntrusiveTagBase<LinkedListNode<T>> {
42
43 constexpr static auto is_sized(InPlaceType<T>) -> bool { return true; }
44 constexpr static auto down_cast(InPlaceType<T>, Node& node) -> T& { return node.value(); }
45
46 constexpr static void did_remove(auto& list, Node& node) {
47 util::destroy_at(util::addressof(node));
48 di::deallocate_one<Node>(list.allocator(), util::addressof(node));
49 }
50 };
51}
52
53template<typename T, concepts::Allocator Alloc = DefaultAllocator>
54class LinkedList : public IntrusiveList<T, detail::LinkedListTag<T>, LinkedList<T, Alloc>> {
55private:
56 using Node = detail::LinkedListNode<T>;
58 using Iterator = meta::ContainerIterator<List>;
59 using ConstIterator = meta::ContainerConstIterator<List>;
60
61 template<concepts::InputContainer Con, typename... Args>
64 auto result = LinkedList {};
65 return invoke_as_fallible([&] {
66 return result.append_container(util::forward<Con>(container));
67 }) % [&] {
68 return util::move(result);
70 }
71
72public:
73 LinkedList() = default;
74
75 LinkedList(LinkedList&&) = default;
76 auto operator=(LinkedList&&) -> LinkedList& = default;
77
78 ~LinkedList() = default;
79
80 constexpr auto insert(ConstIterator position, T const& value) -> Iterator
82 {
83 return emplace(position, value);
84 }
85 constexpr auto insert(ConstIterator position, T&& value) -> Iterator {
86 return emplace(position, util::move(value));
87 }
88
89 template<typename... Args>
90 requires(concepts::ConstructibleFrom<T, Args...>)
91 constexpr auto emplace(ConstIterator position, Args&&... args) -> decltype(auto) {
92 return as_fallible(create_node(util::forward<Args>(args)...)) % [&](Node& node) {
93 return List::insert(position, node);
95 }
96
97 template<concepts::ContainerCompatible<T> Con>
98 constexpr auto insert_container(ConstIterator position, Con&& container) {
99 auto temp = LinkedList {};
100 return invoke_as_fallible([&] {
101 return container::sequence(util::forward<Con>(container), [&]<typename X>(X&& value) {
102 return as_fallible(temp.emplace_back(util::forward<X>(value)));
103 });
104 }) % [&] {
105 this->splice(position, temp);
106 } | try_infallible;
107 }
108
109 constexpr auto push_back(T const& value) -> decltype(auto)
111 {
112 return emplace_back(value);
113 }
114
115 constexpr auto push_back(T&& value) -> decltype(auto) { return emplace_back(util::move(value)); }
116
117 template<typename... Args>
118 requires(concepts::ConstructibleFrom<T, Args...>)
119 constexpr auto emplace_back(Args&&... args) -> decltype(auto) {
120 return as_fallible(emplace(this->end(), util::forward<Args>(args)...)) % [](Iterator it) {
121 return util::ref(*it);
122 } | try_infallible;
123 }
124
125 template<concepts::ContainerCompatible<T> Con>
126 constexpr auto append_container(Con&& container) {
127 return insert_container(this->end(), util::forward<Con>(container));
128 }
129
130 constexpr auto pop_back() -> Optional<T> {
131 if (this->empty()) {
132 return nullopt;
133 }
134 auto last = --this->end();
135 auto value = util::move(*last);
136 this->erase(last);
137 return value;
138 }
139
140 constexpr auto push_front(T const& value) -> decltype(auto)
142 {
143 return emplace_front(value);
144 }
145
146 constexpr auto push_front(T&& value) -> decltype(auto) { return emplace_front(util::move(value)); }
147
148 template<typename... Args>
149 requires(concepts::ConstructibleFrom<T, Args...>)
150 constexpr auto emplace_front(Args&&... args) -> decltype(auto) {
151 return as_fallible(emplace(this->begin(), util::forward<Args>(args)...)) % [](auto it) {
152 return util::ref(*it);
153 } | try_infallible;
154 }
155
156 template<concepts::ContainerCompatible<T> Con>
157 constexpr auto prepend_container(Con&& container) {
158 return insert_container(this->begin(), util::forward<Con>(container));
159 }
160
161 constexpr auto pop_front() -> Optional<T> {
162 if (this->empty()) {
163 return nullopt;
164 }
165 auto first = this->begin();
166 auto value = util::move(*first);
167 this->erase(first);
168 return value;
169 }
170
171 constexpr auto allocator() -> Alloc& { return m_allocator; }
172
173private:
174 template<typename... Args>
175 requires(concepts::ConstructibleFrom<T, Args...>)
176 constexpr auto create_node(Args&&... args) -> decltype(auto) {
177 return as_fallible(di::allocate_one<Node>(m_allocator)) % [&](Node* pointer) {
178 util::construct_at(pointer, in_place, util::forward<Args>(args)...);
179 return util::ref(*pointer);
180 } | try_infallible;
181 }
182
183 [[no_unique_address]] Alloc m_allocator {};
184};
185
186template<concepts::InputContainer Con, typename T = meta::ContainerValue<Con>>
188}
189
190namespace di {
192}
constexpr IntrusiveListNode()
Definition list_node.h:11
constexpr auto insert(ConstIterator position, Node &node_ref) -> Iterator
Definition list.h:154
constexpr void splice(ConstIterator position, IntrusiveList &other)
Definition list.h:197
Definition linked_list.h:54
constexpr auto allocator() -> Alloc &
Definition linked_list.h:171
constexpr auto emplace(ConstIterator position, Args &&... args) -> decltype(auto)
Definition linked_list.h:91
constexpr auto emplace_front(Args &&... args) -> decltype(auto)
Definition linked_list.h:150
constexpr auto insert(ConstIterator position, T const &value) -> Iterator requires(concepts::CopyConstructible< T >)
Definition linked_list.h:80
constexpr auto emplace_back(Args &&... args) -> decltype(auto)
Definition linked_list.h:119
auto operator=(LinkedList &&) -> LinkedList &=default
constexpr friend auto tag_invoke(types::Tag< util::create_in_place >, InPlaceType< LinkedList >, Con &&container)
Definition linked_list.h:63
constexpr auto prepend_container(Con &&container)
Definition linked_list.h:157
constexpr auto append_container(Con &&container)
Definition linked_list.h:126
constexpr auto insert_container(ConstIterator position, Con &&container)
Definition linked_list.h:98
constexpr auto insert(ConstIterator position, T &&value) -> Iterator
Definition linked_list.h:85
constexpr auto push_back(T &&value) -> decltype(auto)
Definition linked_list.h:115
constexpr auto push_front(T const &value) -> decltype(auto) requires(concepts::CopyConstructible< T >)
Definition linked_list.h:140
constexpr auto push_back(T const &value) -> decltype(auto) requires(concepts::CopyConstructible< T >)
Definition linked_list.h:109
LinkedList(LinkedList &&)=default
constexpr auto push_front(T &&value) -> decltype(auto)
Definition linked_list.h:146
constexpr auto pop_back() -> Optional< T >
Definition linked_list.h:130
constexpr auto pop_front() -> Optional< T >
Definition linked_list.h:161
Definition optional_forward_declaration.h:5
Definition operations.h:11
Definition container_compatible.h:9
Definition operations.h:34
Definition input_container.h:8
Definition sequence.h:13
Definition sequence.h:12
constexpr auto sequence
Definition sequence.h:34
constexpr auto erase
Definition erase.h:76
decltype(container::begin(util::declval< T & >())) ContainerIterator
Definition container_iterator.h:8
ConstIterator< ContainerIterator< Con > > ContainerConstIterator
Definition container_const_iterator.h:9
di::meta::Decay< decltype(T)> Tag
Definition tag_invoke.h:28
constexpr auto ref
Definition reference_wrapper.h:98
constexpr auto destroy_at
Definition destroy_at.h:24
constexpr auto construct_at
Definition construct_at.h:27
Definition zstring_parser.h:9
constexpr auto allocate_one
Definition allocate_one.h:29
constexpr tag_invoke_detail::TagInvokeFn tag_invoke
Definition tag_invoke.h:22
constexpr auto invoke_as_fallible
Definition invoke_as_fallible.h:37
constexpr auto as_fallible
Definition as_fallible.h:26
constexpr auto try_infallible
Definition try_infallible.h:31
constexpr auto nullopt
Definition nullopt.h:15
constexpr auto in_place
Definition in_place.h:8
constexpr auto deallocate_one
Definition deallocate_one.h:27
Definition intrusive_tag_base.h:8
Definition linked_list.h:27
constexpr LinkedListNode(InPlace, Args &&... args)
Definition linked_list.h:31
constexpr auto value() -> T &
Definition linked_list.h:33
Definition linked_list.h:40
static constexpr void did_remove(auto &list, Node &node)
Definition linked_list.h:46
LinkedListNode< T > Node
Definition linked_list.h:41
static constexpr auto down_cast(InPlaceType< T >, Node &node) -> T &
Definition linked_list.h:44
static constexpr auto is_sized(InPlaceType< T >) -> bool
Definition linked_list.h:43
Definition in_place_template.h:5
Definition in_place_type.h:5
Definition in_place.h:4