Commit 0ce72890a8fe0ed29f6beb5d515868c67c89be14

Authored by Grzegorz Jabłoński
1 parent dea455b3

Refactored vector

examples11/04-vectortmpl/vector.h
... ... @@ -18,6 +18,42 @@ private:
18 18 return ++w;
19 19 };
20 20  
  21 + void destroy_array(C *ptr, unsigned int s) {
  22 + for (unsigned j = 0; j < s; ++j)
  23 + (ptr + j)->~C();
  24 + free(ptr);
  25 + }
  26 +
  27 + void resize_before_push() {
  28 + if (size >= cap) {
  29 + if (cap > std::numeric_limits<decltype(size)>::max() / (2 * sizeof(C)))
  30 + throw bad_alloc();
  31 + unsigned int newcap = (cap == 0) ? 1 : 2 * cap;
  32 + C *newdata;
  33 + if constexpr (!std::is_trivially_copyable<C>()) {
  34 + newdata = static_cast<C *>(
  35 + std::aligned_alloc(alignof(C), newcap * sizeof(C)));
  36 + if (!newdata)
  37 + throw bad_alloc();
  38 + unsigned i;
  39 + try {
  40 + for (i = 0; i < size; i++)
  41 + new (newdata + i) C(std::move(data[i]));
  42 + } catch (...) {
  43 + destroy_array(newdata, i);
  44 + throw;
  45 + }
  46 + destroy_array(data, size);
  47 + } else {
  48 + newdata = static_cast<C *>(std::realloc(data, newcap * sizeof(C)));
  49 + if (!newdata)
  50 + throw bad_alloc();
  51 + }
  52 + data = newdata;
  53 + cap = newcap;
  54 + }
  55 + }
  56 +
21 57 public:
22 58 class index_out_of_range {};
23 59 explicit vector(unsigned s) {
... ... @@ -34,23 +70,19 @@ public:
34 70 for (i = 0; i < size; i++)
35 71 new (data + i) C();
36 72 } catch (...) {
37   - for (unsigned j = 0; j < i; ++j)
38   - (data + j)->~C();
39   - free(data);
  73 + destroy_array(data, i);
40 74 throw;
41 75 }
42 76 }
43 77  
44   - ~vector() {
45   - for (unsigned j = 0; j < size; ++j)
46   - (data + j)->~C();
47   - free(data);
48   - }
  78 + ~vector() { destroy_array(data, size); }
  79 +
49 80 C &operator[](unsigned int pos) {
50 81 if (pos >= size)
51 82 throw index_out_of_range();
52 83 return data[pos];
53 84 }
  85 +
54 86 C operator[](unsigned int pos) const {
55 87 if (pos >= size)
56 88 throw index_out_of_range();
... ... @@ -68,9 +100,7 @@ public:
68 100 for (i = 0; i < size; i++)
69 101 new (data + i) C(s.data[i]);
70 102 } catch (...) {
71   - for (unsigned j = 0; j < i; ++j)
72   - (data + j)->~C();
73   - free(data);
  103 + destroy_array(data, i);
74 104 throw;
75 105 }
76 106 }
... ... @@ -105,44 +135,9 @@ public:
105 135 }
106 136  
107 137 void push_back(const C &s) {
108   - if (size < cap) {
109   - new (data + size) C(s);
110   - ++size;
111   - } else {
112   - if (cap > std::numeric_limits<decltype(size)>::max() / (2*sizeof(C)))
113   - throw bad_alloc();
114   - unsigned int newcap = (cap == 0) ? 1 : 2 * cap;
115   - C *newdata;
116   - if constexpr (!std::is_trivially_copyable<C>()) {
117   - newdata = static_cast<C *>(
118   - std::aligned_alloc(alignof(C), newcap * sizeof(C)));
119   - if (!newdata)
120   - throw bad_alloc();
121   - unsigned i;
122   - try {
123   - for (i = 0; i < size; i++)
124   - new (newdata + i) C(std::move(data[i]));
125   - } catch (...) {
126   - for (unsigned j = 0; j < i; ++j)
127   - (newdata + j)->~C();
128   - free(newdata);
129   - throw;
130   - }
131   - new (newdata + size) C(s);
132   - for (unsigned j = 0; j < size; ++j)
133   - (data + j)->~C();
134   - free(data);
135   - } else {
136   - newdata = static_cast<C *>(std::realloc(data, newcap * sizeof(C)));
137   - if (!newdata)
138   - throw bad_alloc();
139   - new (newdata + size) C(s);
140   - }
141   -
142   - ++size;
143   - data = newdata;
144   - cap = newcap;
145   - }
  138 + resize_before_push();
  139 + new (data + size) C(s);
  140 + ++size;
146 141 }
147 142 };
148 143 #endif /* __VECTOR_H__ */
... ...