Commit 28f1425350fe9d903a463316f6863786a286a729
1 parent
cac6c667
Added template metaprogramming example to vector
Showing
2 changed files
with
64 additions
and
63 deletions
examples11/06-template_metaprogramming/testvector.cpp
@@ -2,35 +2,26 @@ | @@ -2,35 +2,26 @@ | ||
2 | using namespace std; | 2 | using namespace std; |
3 | #include "vector.h" | 3 | #include "vector.h" |
4 | 4 | ||
5 | -template<class C> void printvector (vector<C> v) | ||
6 | -{ | ||
7 | - cout << v << endl; | ||
8 | -} | ||
9 | - | ||
10 | -int | ||
11 | -main () | ||
12 | -{ | ||
13 | - vector<int> a (10); | ||
14 | - cout << a << endl; | ||
15 | - a[0] = 15; | ||
16 | - a[5] = 32; | ||
17 | - vector<int> b(10); | ||
18 | - a.push_back(4); | ||
19 | - a.push_back(5); | ||
20 | - a.push_back(6); | ||
21 | - a.push_back(7); | ||
22 | - a.push_back(8); | ||
23 | - a.push_back(9); | ||
24 | - a.push_back(10); | ||
25 | - cout << a.push_back(11) << endl; | ||
26 | - auto x = a.push_back(12,13,14); | ||
27 | - cout << get<0>(x) << endl; | ||
28 | - cout << get<0>(get<1>(x)) << endl; | ||
29 | - cout << get<0>(get<1>(get<1>(x))) << endl; | 5 | +template <class C> void printvector(vector<C> v) { cout << v << endl; } |
30 | 6 | ||
31 | - int arg = 15; | 7 | +int main() { |
8 | + vector<string> a(0); | ||
9 | + vector<string> b(0); | ||
10 | + a.push_back("1"); | ||
11 | + a.push_back("2"); | ||
12 | + a.push_back("3"); | ||
13 | + a.push_back("4"); | ||
14 | + a.push_back("5"); | ||
15 | + a.push_back("6"); | ||
16 | + a.push_back("7"); | ||
17 | + a.reserve(11); // to avoid reallocation and reference invalidation | ||
18 | + auto [x, y, z] = a.push_back("8", "9", "10"); | ||
19 | + printvector(a); | ||
20 | + x = "108"; | ||
21 | + y = "109"; | ||
22 | + z = "110"; | ||
23 | + string arg = "11"; | ||
32 | a.push_back(arg); | 24 | a.push_back(arg); |
33 | - b=a; | ||
34 | - printvector (b); | ||
35 | - | 25 | + b = a; |
26 | + printvector(b); | ||
36 | } | 27 | } |
examples11/06-template_metaprogramming/vector.h
@@ -2,8 +2,8 @@ | @@ -2,8 +2,8 @@ | ||
2 | #define __VECTOR_H__ | 2 | #define __VECTOR_H__ |
3 | #include <cstring> | 3 | #include <cstring> |
4 | #include <limits> | 4 | #include <limits> |
5 | -#include <type_traits> | ||
6 | #include <tuple> | 5 | #include <tuple> |
6 | +#include <type_traits> | ||
7 | 7 | ||
8 | template <class C> class vector { | 8 | template <class C> class vector { |
9 | C *data; | 9 | C *data; |
@@ -25,33 +25,37 @@ private: | @@ -25,33 +25,37 @@ private: | ||
25 | free(ptr); | 25 | free(ptr); |
26 | } | 26 | } |
27 | 27 | ||
28 | + void reserve_internal(unsigned capacity) { | ||
29 | + unsigned int newcap = capacity; | ||
30 | + C *newdata; | ||
31 | + if constexpr (!std::is_trivially_copyable<C>()) { | ||
32 | + newdata = | ||
33 | + static_cast<C *>(std::aligned_alloc(alignof(C), newcap * sizeof(C))); | ||
34 | + if (!newdata) | ||
35 | + throw bad_alloc(); | ||
36 | + unsigned i; | ||
37 | + try { | ||
38 | + for (i = 0; i < size; i++) | ||
39 | + new (newdata + i) C(std::move(data[i])); | ||
40 | + } catch (...) { | ||
41 | + destroy_array(newdata, i); | ||
42 | + throw; | ||
43 | + } | ||
44 | + destroy_array(data, size); | ||
45 | + } else { | ||
46 | + newdata = static_cast<C *>(std::realloc(data, newcap * sizeof(C))); | ||
47 | + if (!newdata) | ||
48 | + throw bad_alloc(); | ||
49 | + } | ||
50 | + data = newdata; | ||
51 | + cap = newcap; | ||
52 | + } | ||
53 | + | ||
28 | void resize_before_push() { | 54 | void resize_before_push() { |
29 | if (size >= cap) { | 55 | if (size >= cap) { |
30 | if (cap > std::numeric_limits<decltype(size)>::max() / (2 * sizeof(C))) | 56 | if (cap > std::numeric_limits<decltype(size)>::max() / (2 * sizeof(C))) |
31 | throw bad_alloc(); | 57 | throw bad_alloc(); |
32 | - unsigned int newcap = (cap == 0) ? 1 : 2 * cap; | ||
33 | - C *newdata; | ||
34 | - if constexpr (!std::is_trivially_copyable<C>()) { | ||
35 | - newdata = static_cast<C *>( | ||
36 | - std::aligned_alloc(alignof(C), newcap * sizeof(C))); | ||
37 | - if (!newdata) | ||
38 | - throw bad_alloc(); | ||
39 | - unsigned i; | ||
40 | - try { | ||
41 | - for (i = 0; i < size; i++) | ||
42 | - new (newdata + i) C(std::move(data[i])); | ||
43 | - } catch (...) { | ||
44 | - destroy_array(newdata, i); | ||
45 | - throw; | ||
46 | - } | ||
47 | - destroy_array(data, size); | ||
48 | - } else { | ||
49 | - newdata = static_cast<C *>(std::realloc(data, newcap * sizeof(C))); | ||
50 | - if (!newdata) | ||
51 | - throw bad_alloc(); | ||
52 | - } | ||
53 | - data = newdata; | ||
54 | - cap = newcap; | 58 | + reserve_internal((cap == 0) ? 1 : 2 * cap); |
55 | } | 59 | } |
56 | } | 60 | } |
57 | 61 | ||
@@ -150,20 +154,26 @@ private: | @@ -150,20 +154,26 @@ private: | ||
150 | } | 154 | } |
151 | 155 | ||
152 | public: | 156 | public: |
153 | - | ||
154 | - C& push_back(C&& s) | ||
155 | - { | ||
156 | - return push_back_single(std::forward<C>(s)); | 157 | + void reserve(unsigned capacity) { |
158 | + if (capacity > std::numeric_limits<decltype(size)>::max() / (2 * sizeof(C))) | ||
159 | + throw bad_alloc(); | ||
160 | + unsigned int cap_rounded_up = round_up_to_power_of_2(capacity); | ||
161 | + reserve_internal(cap_rounded_up); | ||
157 | } | 162 | } |
158 | 163 | ||
159 | - std::tuple<> push_back() | ||
160 | - { | ||
161 | - return std::tuple<>{}; | 164 | + std::tuple<C &> push_back(C &&s) { |
165 | + C &r = push_back_single(std::forward<C>(s)); | ||
166 | + return std::tuple<C &>(r); | ||
162 | } | 167 | } |
163 | 168 | ||
164 | - template <class T, class... Args> auto push_back(T&& a, Args &&... args) { | ||
165 | - return std::tuple(push_back(std::forward<C>(a)),push_back(args...)); | ||
166 | - } | 169 | +private: |
170 | + std::tuple<> push_back() { return std::tuple<>(); } | ||
167 | 171 | ||
172 | +public: | ||
173 | + template <class T, class... Args> auto push_back(T &&a, Args &&... args) { | ||
174 | + auto op1 = push_back(std::forward<C>(a)); | ||
175 | + auto op2 = push_back(args...); | ||
176 | + return std::tuple_cat(op1, op2); | ||
177 | + } | ||
168 | }; | 178 | }; |
169 | #endif /* __VECTOR_H__ */ | 179 | #endif /* __VECTOR_H__ */ |