Эх сурвалжийг харах

list with placement new for efficient adding

Kajetan Johannes Hammerle 3 жил өмнө
parent
commit
b454ba74fc
2 өөрчлөгдсөн 239 нэмэгдсэн , 1 устгасан
  1. 122 1
      Main.cpp
  2. 117 0
      utils/List.h

+ 122 - 1
Main.cpp

@@ -1,9 +1,12 @@
 #include <iostream>
+#include <vector>
 
 #include "utils/HashMap.h"
+#include "utils/List.h"
 
 constexpr int MAP_MIN_CAPACITY = 5;
 typedef HashMap<int, int, MAP_MIN_CAPACITY> IntMap;
+typedef List<int, 20> IntList;
 
 const char* RED = "\033[0;31m";
 const char* GREEN = "\033[0;32m";
@@ -13,7 +16,7 @@ int successTests = 0;
 
 void finalizeTest() {
     std::cout << ((successTests == tests) ? GREEN : RED);
-    std::cout << successTests << " / " << tests << " succeeded\n";
+    std::cout << successTests << " / " << tests << " succeeded\n\n";
     tests = 0;
     successTests = 0;
 }
@@ -92,7 +95,125 @@ namespace Map {
     }
 }
 
+namespace TestList {
+
+    void testAdd() {
+        IntList list;
+        list.add(5);
+        
+        checkEqual(5, list[0], "list contains added value");
+        checkEqual(1, list.getLength(), "list sizes is increased by add");
+    }
+
+    void testMultipleAdd() {
+        IntList list;
+        list.add(4);
+        list.add(3);
+        list.add(2);
+        checkEqual(4, list[0], "list contains added value");
+        checkEqual(3, list[1], "list contains added value");
+        checkEqual(2, list[2], "list contains added value");
+        checkEqual(3, list.getLength(), "list sizes is increased by add");
+    }
+
+    void testAddReplace() {
+        IntList list;
+        list.add(5);
+        list[0] = 3;
+        checkEqual(3, list[0], "list value is overwritten");
+    }
+
+    void testClear() {
+        IntList list;
+        list.add(5);
+        list.add(4);
+        list.clear();
+
+        checkEqual(0, list.getLength(), "list length is 0 after clear");
+    }
+
+    void testOverflow() {
+        IntList list;
+        for(int i = 0; i < 1000000; i++) {
+            list.add(i);
+        }
+        for(int i = 0; i < list.getLength(); i++) {
+            checkEqual(i, list[i], "list still contains values after overflow");
+        }
+        checkEqual(true, true, "list survives overflow");
+    }
+    
+    void testCopy() {
+        IntList list;
+        list.add(1);
+        list.add(2);
+        list.add(3);
+        
+        IntList copy(list);
+        checkEqual(list.getLength(), copy.getLength(), "list copy has same length");
+        for(int i = 0; i < copy.getLength() && i < list.getLength(); i++) {
+            checkEqual(list[i], copy[i], "list copy has same values");
+        }
+    }
+    
+    void testCopyAssignment() {
+        IntList list;
+        list.add(1);
+        list.add(2);
+        list.add(3);
+        
+        IntList copy;
+        copy = list;
+        checkEqual(list.getLength(), copy.getLength(), "list copy assignment has same length");
+        for(int i = 0; i < copy.getLength() && i < list.getLength(); i++) {
+            checkEqual(list[i], copy[i], "list copy assignment has same values");
+        }
+    }
+    
+    void testMove() {
+        IntList list;
+        list.add(1);
+        list.add(2);
+        list.add(3);
+        
+        IntList move(std::move(list));
+        checkEqual(0, list.getLength(), "moved list has length 0");
+        checkEqual(3, move.getLength(), "moved list passes length");
+        checkEqual(1, move[0], "moved list passes values");
+        checkEqual(2, move[1], "moved list passes values");
+        checkEqual(3, move[2], "moved list passes values");
+    }
+    
+    void testMoveAssignment() {
+        IntList list;
+        list.add(1);
+        list.add(2);
+        list.add(3);
+        
+        IntList move(std::move(list));
+        checkEqual(0, list.getLength(), "assignment moved list has length 0");
+        checkEqual(3, move.getLength(), "assignment moved list passes length");
+        checkEqual(1, move[0], "assignment moved list passes values");
+        checkEqual(2, move[1], "assignment moved list passes values");
+        checkEqual(3, move[2], "assignment moved list passes values");
+    }
+
+    void test() {
+        testAdd();
+        testMultipleAdd();
+        testAddReplace();
+        testClear();
+        testOverflow();
+        testCopy();
+        testCopyAssignment();
+        testMove();
+        testMoveAssignment();
+        finalizeTest();
+    }
+}
+
 int main() {
     Map::test();
+    TestList::test();
     return 0;
 }

+ 117 - 0
utils/List.h

@@ -0,0 +1,117 @@
+#ifndef LIST_H
+#define LIST_H
+
+#include <utility>
+
+template<typename T, int N>
+class List final {
+    char data[sizeof (T) * N];
+    int index = 0;
+
+    void copy(const List& other) {
+        for(int i = 0; i < other.index; i++) {
+            add(other[i]);
+        }
+    }
+
+    void move(List&& other) {
+        for(int i = 0; i < other.index; i++) {
+            add(std::move(other[i]));
+        }
+    }
+
+public:
+    List() = default;
+
+    void clear() {
+        for(int i = 0; i < index; i++) {
+            (*this)[i].~T();
+        }
+        index = 0;
+    }
+
+    ~List() {
+        clear();
+    }
+
+    List(const List& other) : index(0) {
+        copy(other);
+    }
+
+    List& operator=(const List& other) {
+        if(&other != this) {
+            clear();
+            copy(other);
+        }
+        return *this;
+    }
+
+    List(List&& other) : index(0) {
+        move(std::move(other));
+        other.clear();
+    }
+
+    List& operator=(List&& other) {
+        if(&other != this) {
+            clear();
+            move(std::move(other));
+            other.clear();
+        }
+        return *this;
+    }
+
+    T* begin() {
+        return reinterpret_cast<T*> (data);
+    }
+
+    T* end() {
+        return reinterpret_cast<T*> (data) + index;
+    }
+
+    const T* begin() const {
+        return reinterpret_cast<const T*> (data);
+    }
+
+    const T* end() const {
+        return reinterpret_cast<const T*> (data) + index;
+    }
+
+    void add(const T& t) {
+        if(index >= N) {
+            return;
+        }
+        new (end()) T(t);
+        index++;
+    }
+
+    void add(T&& t) {
+        if(index >= N) {
+            return;
+        }
+        new (end()) T(std::move(t));
+        index++;
+    }
+
+    template<typename... Args>
+    void add(Args&&... args) {
+        if(index >= N) {
+            return;
+        }
+        new (end()) T(args...);
+        index++;
+    }
+
+    T& operator[](int index) {
+        return begin()[index];
+    }
+
+    const T& operator[](int index) const {
+        return begin()[index];
+    }
+
+    int getLength() const {
+        return index;
+    }
+};
+
+#endif