jiwoo
Automatic memory management of containers of array pointers
Loading...
Searching...
No Matches
EquilengthArrays.hpp
Go to the documentation of this file.
1#ifndef JIWOO_EQUILENGTH_ARRAYS_HPP
2#define JIWOO_EQUILENGTH_ARRAYS_HPP
3
4#include <algorithm>
5#include <cstddef>
6#include <type_traits>
7
13namespace jiwoo {
14
22template<typename Value_>
24public:
29 EquilengthArrays() = default;
30
38 EquilengthArrays(std::size_t size, std::size_t length) : my_size(size), my_length(length) {
39 my_ptr = safely_allocate(
40 size,
41 length,
42 [](std::size_t, Value_*) -> void {}
43 );
44 }
45
51 EquilengthArrays(std::size_t size, std::size_t length, Value_ fill) : my_size(size), my_length(length) {
52 my_ptr = safely_allocate(
53 size,
54 length,
55 [&](std::size_t, Value_* ptr) -> void {
56 std::fill_n(ptr, length, fill);
57 }
58 );
59 }
60
66 EquilengthArrays(const EquilengthArrays& other) : my_size(other.my_size), my_length(other.my_length) {
67 my_ptr = safely_allocate(
68 my_size,
69 my_length,
70 [&](std::size_t i, Value_* ptr) -> void {
71 std::copy_n(other.my_ptr[i], my_length, ptr);
72 }
73 );
74 }
75
82 EquilengthArrays(EquilengthArrays&& other) noexcept : my_ptr(other.my_ptr), my_size(other.my_size), my_length(other.my_length) {
83 other.my_size = 0;
84 other.my_ptr = NULL;
85 }
86
87private:
88 Value_** my_ptr = NULL;
89 std::size_t my_size = 0;
90 std::size_t my_length = 0;
91
92 template<typename Extra_>
93 static Value_** safely_allocate(std::size_t size, std::size_t length, Extra_ extra) {
94 Value_** output = new Value_* [size];
95
96 std::size_t allocated = 0;
97 try {
98 for (std::size_t i = 0; i < size; ++i) {
99 output[i] = new Value_ [length];
100 ++allocated;
101 extra(i, output[i]);
102 }
103 } catch(...) {
104 for (std::size_t x = 0; x < allocated; ++x) {
105 delete [] output[x];
106 }
107 delete[] output;
108 throw;
109 }
110
111 return output;
112 }
113
114public:
119 if (my_ptr != NULL) {
120 for (std::size_t i = 0; i < my_size; ++i) {
121 delete [] my_ptr[i];
122 }
123 delete [] my_ptr;
124 }
125 }
126
127public:
136 // If the memory is already available and correctly sized, we can just copy it in.
137 // We only attempt this if the copy assignment is nothrow, as this ensures we can't crash with a half-copied object.
138 // Obviously no copying is necessary at all if it's a self assignment.
139 if constexpr(std::is_nothrow_copy_assignable<Value_>::value) {
140 if (other.my_size == my_size && other.my_length == my_length) {
141 if (other.my_ptr != my_ptr) {
142 for (std::size_t i = 0; i < my_size; ++i) {
143 std::copy_n(other.my_ptr[i], my_length, my_ptr[i]);
144 }
145 }
146 return *this;
147 }
148 }
149
150 // One might be tempted to optimize for the situation where 'other.my_size == my_size', and just reallocate the inner arrays.
151 // The problem is that, if there's an allocation error and the move assignment fails halfway through the inner arrays,
152 // we'll end up with a frankenobject for which 'my_length' is not correct.
153
154 // Copy and swap idiom.
155 EquilengthArrays tmp(other);
156 swap(tmp);
157 return *this;
158 }
159
167 // Copy and swap idiom.
168 EquilengthArrays tmp(std::move(other));
169 swap(tmp);
170 return *this;
171 }
172
177 void swap(EquilengthArrays& other) noexcept {
178 std::swap(other.my_size, my_size);
179 std::swap(other.my_length, my_length);
180 std::swap(other.my_ptr, my_ptr);
181 }
182
183public:
187 std::size_t size() const {
188 return my_size;
189 }
190
194 std::size_t length() const {
195 return my_length;
196 }
197
201 bool empty() const {
202 return my_size == 0;
203 }
204public:
210 Value_* operator[](std::size_t i) {
211 return my_ptr[i];
212 }
213
219 const Value_* operator[](std::size_t i) const {
220 return my_ptr[i];
221 }
222
223public:
227 Value_* const* get() {
228 return my_ptr;
229 }
230
234 const Value_* const * get() const {
235 return my_ptr;
236 }
237
238public:
244 Value_* front() {
245 return my_ptr[0];
246 }
247
253 const Value_* front() const {
254 return my_ptr[0];
255 }
256
257public:
263 Value_* back() {
264 return my_ptr[my_size - 1];
265 }
266
272 const Value_* back() const {
273 return my_ptr[my_size - 1];
274 }
275
276public:
281 Value_* const* begin() {
282 return my_ptr;
283 }
284
289 const Value_* const* begin() const {
290 return my_ptr;
291 }
292
293public:
298 Value_* const* end() {
299 return my_ptr + my_size;
300 }
301
306 const Value_* const* end() const {
307 return my_ptr + my_size;
308 }
309};
310
311}
312
313#endif
Array of equilength arrays.
Definition EquilengthArrays.hpp:23
bool empty() const
Definition EquilengthArrays.hpp:201
const Value_ * back() const
Definition EquilengthArrays.hpp:272
Value_ * front()
Definition EquilengthArrays.hpp:244
EquilengthArrays & operator=(EquilengthArrays &&other) noexcept
Definition EquilengthArrays.hpp:166
Value_ *const * begin()
Definition EquilengthArrays.hpp:281
EquilengthArrays(std::size_t size, std::size_t length, Value_ fill)
Definition EquilengthArrays.hpp:51
EquilengthArrays(std::size_t size, std::size_t length)
Definition EquilengthArrays.hpp:38
const Value_ * operator[](std::size_t i) const
Definition EquilengthArrays.hpp:219
Value_ *const * get()
Definition EquilengthArrays.hpp:227
std::size_t length() const
Definition EquilengthArrays.hpp:194
const Value_ *const * end() const
Definition EquilengthArrays.hpp:306
EquilengthArrays & operator=(const EquilengthArrays &other)
Definition EquilengthArrays.hpp:135
const Value_ *const * begin() const
Definition EquilengthArrays.hpp:289
Value_ *const * end()
Definition EquilengthArrays.hpp:298
const Value_ * front() const
Definition EquilengthArrays.hpp:253
std::size_t size() const
Definition EquilengthArrays.hpp:187
Value_ * back()
Definition EquilengthArrays.hpp:263
~EquilengthArrays()
Definition EquilengthArrays.hpp:118
Value_ * operator[](std::size_t i)
Definition EquilengthArrays.hpp:210
void swap(EquilengthArrays &other) noexcept
Definition EquilengthArrays.hpp:177
const Value_ *const * get() const
Definition EquilengthArrays.hpp:234
EquilengthArrays(const EquilengthArrays &other)
Definition EquilengthArrays.hpp:66
EquilengthArrays(EquilengthArrays &&other) noexcept
Definition EquilengthArrays.hpp:82
Automatic memory management of array pointers.
Definition EquilengthArrays.hpp:13