C++ Library Extensions 2022.12.09
To help learn modern C++ programming
050-stl_extension.cpp
Go to the documentation of this file.
1#include <tpf_output.hpp>
2
5
7{
8 private:
9 mutable bool m_invalid{false};
10
11 void invalidate()
12 {
13 this->m_invalid = true;
14 }
15
16 void cleanup()
17 {
18 if(this->m_invalid == false)
19 stream <<"Cleaned up" << endl;
20 }
21
22 public:
24 {
25 stream <<"Default constructor called" << endl;
26 }
27
29 {
30 stream <<"Constructor(int n) called" << endl;
31 }
32
34 {
35 stream << "Copy constructor called" << endl;
36 }
37
39 {
40 stream <<"Copy assignment operator called" << endl;
41 return *this;
42 }
43
44 copy_or_move(copy_or_move&& rhs) noexcept
45 {
46 stream << "Move constructor called" << endl;
47 rhs.invalidate();
48 }
49
51 {
52 stream <<"Move assignment operator called" << endl;
53 rhs.invalidate();
54
55 return *this;
56 }
57
59 {
60 cleanup();
61 }
62};
63
65{
66 return {1};
67}
68
70{
71 auto obj = copy_elision();
72}
73
74copy_or_move return_prvalue(int n = 2, int m = 1)
75{
76 auto obj = copy_elision();
77
78 if(n > m)
79 {
80 return obj;
81 }
82 else
83 return {1};
84}
85
87{
88 auto obj = return_prvalue();
89}
90
91template<typename ElementType, template<typename, typename...> class ContainerType>
92class stl_extension: public ContainerType<ElementType>
93{
94 public:
95
96 using base_container_type = ContainerType<ElementType>;
97 using ContainerType<ElementType>::ContainerType;
98 using iterator = typename ContainerType<ElementType>::iterator;
99 using size_type = typename ContainerType<ElementType>::size_type;
100
101 public:
102
104 {
105 return std::make_move_iterator<iterator>(base_container_type::begin());
106 }
107
109 {
110 return std::make_move_iterator<iterator>(base_container_type::end());
111 }
112
113 auto index_to_iterator(size_type index) noexcept
114 {
115 auto itr = base_container_type::begin();
116 std::advance(itr, index);
117 return itr;
118 }
119
121 {
122 return std::distance(base_container_type::begin(), itr);
123 }
124
126 {
127 return std::make_move_iterator<decltype(itr)>(itr);
128 }
129
131 {
132 auto itr = base_container_type::begin();
133 std::advance(itr, index);
134
135 return std::make_move_iterator<decltype(itr)>(itr);
136 }
137
138 private:
139
140 decltype(auto) internal_move_item(iterator itr)
141 {
142 return *std::make_move_iterator<decltype(itr)>(itr);
143 }
144
145 decltype(auto) internal_move_item(size_type index)
146 {
147 auto itr = base_container_type::begin();
148 std::advance(itr, index);
149 return *std::make_move_iterator<decltype(itr)>(itr);
150 }
151
152 public:
153
154 template<typename Type = ElementType>
155 std::enable_if_t< std::is_same_v<Type, ElementType>
156 && std::is_move_constructible_v<ElementType>, ElementType>
158 {
159 auto itr = base_container_type::begin();
160 auto named_return_value = internal_move_item(itr);
161
162 if constexpr( tpf::types::is_pop_front_available_v<base_container_type> )
164 else
166
167 return named_return_value; // named return value optimization
168 }
169
170 template<typename Type = ElementType>
171 std::enable_if_t< std::is_same_v<Type, ElementType>
172 && std::is_move_constructible_v<ElementType>, ElementType>
174 {
175 auto itr = base_container_type::end();
176 std::advance(itr, -1); // last element
177
178 auto named_return_value = internal_move_item(itr);
179
180 if constexpr( tpf::types::is_pop_back_available_v<base_container_type>)
182 else
184
185 return named_return_value; // named return value optimization
186 }
187
188 template<typename Type = ElementType>
189 std::enable_if_t< std::is_same_v<Type, ElementType>
190 && std::is_move_constructible_v<ElementType>, ElementType>
191 move(typename base_container_type::iterator itr)
192 {
193 auto named_return_value = internal_move_item(itr);
195
196 return named_return_value; // named return value optimization
197 }
198
199 template<typename Type = ElementType>
200 std::enable_if_t< std::is_same_v<Type, ElementType>
201 && std::is_move_constructible_v<ElementType>, ElementType>
202 move(typename base_container_type::size_type index)
203 {
204 return this->move(to_iterator(index)); // copy elision
205 }
206
207 template<typename Type = ElementType>
208 std::enable_if_t< std::is_same_v<Type, ElementType>
209 && std::is_move_constructible_v<ElementType>, ElementType>
210 move(typename base_container_type::iterator itr_begin,
211 typename base_container_type::iterator itr_end)
212 {
213 auto named_return_value =
214 base_container_type{ make_move_iterator(itr_begin), make_move_iterator(itr_end) };
215
216 base_container_type::erase(itr_begin, itr_end);
217
218 return named_return_value; // named return value optimization
219 }
220
221 template<typename Type = ElementType>
222 std::enable_if_t< std::is_same_v<Type, ElementType>
223 && std::is_move_constructible_v<ElementType>, ElementType>
224 move(typename base_container_type::size_type index_begin,
225 typename base_container_type::size_type index_end) noexcept(false) // CAN throw exception
226 {
227 return this->move(to_iterator(index_begin), to_iterator(index_end));
228 }
229};
230
231template<typename ElementType, template<typename, typename...> class ContainerType>
233
234
236{
238
239 ext_vector_t vctr; vctr.reserve(10);
240
241 vctr.emplace_back(1);
242 vctr.emplace_back(2);
243
244 stream << endl << endl;
245
246 auto back = vctr.move_back();
247
248 auto front = vctr.move_front();
249
250 stream << "Size: " << vctr.size() << endl;
251
252}
253
254
255
256int main()
257{
258 // test_copy_elision();
259 // test_which_constructor_gets_called();
261
262 std::vector<int> v;
263
264 v.back();
265
266 v.pop_back();
267}
void test_which_constructor_gets_called()
tpf::sstream stream
copy_or_move copy_elision()
void test_stl_extension()
copy_or_move return_prvalue(int n=2, int m=1)
auto endl
void test_copy_elision()
int main()
copy_or_move & operator=(const copy_or_move &rhs)
copy_or_move(const copy_or_move &rhs)
copy_or_move(copy_or_move &&rhs) noexcept
copy_or_move & operator=(copy_or_move &&rhs)
std::enable_if_t< std::is_same_v< Type, ElementType > &&std::is_move_constructible_v< ElementType >, ElementType > move(typename base_container_type::size_type index)
std::enable_if_t< std::is_same_v< Type, ElementType > &&std::is_move_constructible_v< ElementType >, ElementType > move_back()
std::enable_if_t< std::is_same_v< Type, ElementType > &&std::is_move_constructible_v< ElementType >, ElementType > move_front()
auto iterator_to_index(iterator itr)
ContainerType< ElementType > base_container_type
typename ContainerType< ElementType >::size_type size_type
auto index_to_move_iterator(size_type index) noexcept
auto index_to_iterator(size_type index) noexcept
auto interator_to_move_iterator(iterator itr) noexcept
typename ContainerType< ElementType >::iterator iterator
std::enable_if_t< std::is_same_v< Type, ElementType > &&std::is_move_constructible_v< ElementType >, ElementType > move(typename base_container_type::size_type index_begin, typename base_container_type::size_type index_end) noexcept(false)
std::enable_if_t< std::is_same_v< Type, ElementType > &&std::is_move_constructible_v< ElementType >, ElementType > move(typename base_container_type::iterator itr_begin, typename base_container_type::iterator itr_end)
std::enable_if_t< std::is_same_v< Type, ElementType > &&std::is_move_constructible_v< ElementType >, ElementType > move(typename base_container_type::iterator itr)
auto erase(ContainerType< EleType, Types... > &container, size_t index)
Definition: tpf_types.hpp:7026
auto pop_front(ContainerType< Type, Types... > &container)
Definition: tpf_types.hpp:7034
auto pop_back(ContainerType< Type, Types... > &container)
Definition: tpf_types.hpp:7074
constexpr auto endl
Definition: tpf_output.hpp:973
Stream output operators << are implemented.