Parcourir la source

uninitialized array

Kajetan Johannes Hammerle il y a 3 ans
Parent
commit
efdb12fd1c
2 fichiers modifiés avec 78 ajouts et 19 suppressions
  1. 17 19
      utils/List.h
  2. 61 0
      utils/UninitializedArray.h

+ 17 - 19
utils/List.h

@@ -1,14 +1,12 @@
 #ifndef LIST_H
 #define LIST_H
 
-#include <new>
-#include <utility>
-
+#include "utils/UninitializedArray.h"
 #include "utils/StringBuffer.h"
 
 template<typename T, int N>
 class List final {
-    char data[sizeof (T) * N];
+    UninitializedArray<T, N> data;
     int length = 0;
 
     void copy(const List& other) {
@@ -28,7 +26,7 @@ public:
 
     void clear() {
         for(int i = 0; i < length; i++) {
-            (*this)[i].~T();
+            data.destroy(i);
         }
         length = 0;
     }
@@ -64,26 +62,26 @@ public:
     }
 
     T* begin() {
-        return reinterpret_cast<T*> (data);
+        return data.begin();
     }
 
     T* end() {
-        return reinterpret_cast<T*> (data) + length;
+        return data.end();
     }
 
     const T* begin() const {
-        return reinterpret_cast<const T*> (data);
+        return data.begin();
     }
 
     const T* end() const {
-        return reinterpret_cast<const T*> (data) + length;
+        return data.end();
     }
 
     bool add(const T& t) {
         if(length >= N) {
             return true;
         }
-        new (end()) T(t);
+        data.init(length, t);
         length++;
         return false;
     }
@@ -92,7 +90,7 @@ public:
         if(length >= N) {
             return true;
         }
-        new (end()) T(std::move(t));
+        data.init(length, std::move(t));
         length++;
         return false;
     }
@@ -102,17 +100,17 @@ public:
         if(length >= N) {
             return true;
         }
-        new (end()) T(std::forward<Args>(args)...);
+        data.init(length, std::forward<Args>(args)...);
         length++;
         return false;
     }
 
     T& operator[](int index) {
-        return begin()[index];
+        return data[index];
     }
 
     const T& operator[](int index) const {
-        return begin()[index];
+        return data[index];
     }
 
     int getLength() const {
@@ -123,11 +121,11 @@ public:
     void toString(StringBuffer<L>& s) const {
         s.append("[");
         for(int i = 0; i < length - 1; i++) {
-            s.append((*this)[i]);
+            s.append(data[i]);
             s.append(", ");
         }
         if(length > 0) {
-            s.append((*this)[length - 1]);
+            s.append(data[length - 1]);
         }
         s.append("]");
     }
@@ -136,12 +134,12 @@ public:
         if(index < 0 || index >= length) {
             return true;
         } else if(index + 1 == length) {
-            (*this)[index].~T();
+            data.destroy(index);
             length--;
             return false;
         }
-        (*this)[index] = std::move((*this)[length - 1]);
-        (*this)[length - 1].~T();
+        data[index] = std::move(data[length - 1]);
+        data.destroy(length - 1);
         length--;
         return false;
     }

+ 61 - 0
utils/UninitializedArray.h

@@ -0,0 +1,61 @@
+#ifndef UNINITIALIZEDARRAY_H
+#define UNINITIALIZEDARRAY_H
+
+#include <new>
+#include <utility>
+#include <vector>
+
+template<typename T, int N>
+class UninitializedArray final {
+    char data[sizeof (T) * N];
+
+public:
+    UninitializedArray() = default;
+    UninitializedArray(const UninitializedArray&) = delete;
+    UninitializedArray(UninitializedArray&&) = delete;
+    UninitializedArray& operator=(const UninitializedArray&) = delete;
+    UninitializedArray& operator=(UninitializedArray&&) = delete;
+    
+    T* begin() {
+        return reinterpret_cast<T*> (data);
+    }
+
+    T* end() {
+        return begin() + N;
+    }
+
+    const T* begin() const {
+        return reinterpret_cast<const T*> (data);
+    }
+
+    const T* end() const {
+        return begin() + N;
+    }
+    
+    T& operator[](int index) {
+        return begin()[index];
+    }
+
+    const T& operator[](int index) const {
+        return begin()[index];
+    }
+    
+    void init(int index, const T& t) {
+        new (begin() + index) T(t);
+    }
+
+    void init(int index, T&& t) {
+        new (begin() + index) T(std::move(t));
+    }
+
+    template<typename... Args>
+    void init(int index, Args&&... args) {
+        new (begin() + index) T(std::forward<Args>(args)...);
+    }
+    
+    void destroy(int index) {
+        begin()[index].~T();
+    }
+};
+
+#endif