Browse Source

removed a lot of code redundency with templates in hashmap, removed
duplicate adds in containers which use perfect forwarding

Kajetan Johannes Hammerle 1 year ago
parent
commit
a024f50e7c
6 changed files with 55 additions and 201 deletions
  1. 0 16
      data/ArrayList.h
  2. 53 160
      data/HashMap.h
  3. 0 12
      data/List.h
  4. 1 11
      data/Stack.h
  5. 0 1
      tests/HashMapTests.cpp
  6. 1 1
      tests/StackTests.cpp

+ 0 - 16
data/ArrayList.h

@@ -61,22 +61,6 @@ public:
         return begin() + length;
     }
 
-    bool add(const T& t) {
-        if(length >= N) {
-            return true;
-        }
-        new(begin() + length++) T(t);
-        return false;
-    }
-
-    bool add(T&& t) {
-        if(length >= N) {
-            return true;
-        }
-        new(begin() + length++) T(std::move(t));
-        return false;
-    }
-
     template<typename... Args>
     bool add(Args&&... args) {
         if(length >= N) {

+ 53 - 160
data/HashMap.h

@@ -21,45 +21,37 @@ struct HashMap final {
         }
 
     private:
-        int next;
-
-        Node(const K& key, const V& value) : key(key), value(value), next(-1) {
-        }
-
-        Node(const K& key, V&& value)
-            : key(key), value(std::move(value)), next(-1) {
-        }
-
         template<typename... Args>
         Node(const K& key, Args&&... args)
-            : key(key), value(std::forward<Args>(args)...), next(-1) {
+            : key(key), value(std::forward<Args>(args)...) {
         }
     };
+    using Nodes = List<List<Node>>;
 
-    template<typename N, typename R>
-    class BaseEntryIterator final {
+    template<typename N, typename I, typename R, R& (*A)(I&)>
+    class Iterator final {
         N& nodes;
         int indexA;
         int indexB;
 
     public:
-        BaseEntryIterator(N& nodes, int indexA, int indexB)
+        Iterator(N& nodes, int indexA, int indexB)
             : nodes(nodes), indexA(indexA), indexB(indexB) {
             skip();
         }
 
-        BaseEntryIterator& operator++() {
+        Iterator& operator++() {
             indexB++;
             skip();
             return *this;
         }
 
-        bool operator!=(const BaseEntryIterator& other) const {
+        bool operator!=(const Iterator& other) const {
             return indexA != other.indexA || indexB != other.indexB;
         }
 
-        R& operator*() {
-            return nodes[indexA][indexB];
+        R& operator*() const {
+            return A(nodes[indexA][indexB]);
         }
 
     private:
@@ -72,147 +64,60 @@ struct HashMap final {
         }
     };
 
-    typedef BaseEntryIterator<List<List<Node>>, Node> EntryIterator;
-    typedef BaseEntryIterator<const List<List<Node>>, const Node>
-        ConstEntryIterator;
-
-    struct EntryIteratorAdapter final {
-        HashMap& map;
-
-        EntryIterator begin() {
-            return EntryIterator(map.nodes, 0, 0);
-        }
-
-        EntryIterator end() {
-            return EntryIterator(map.nodes, map.nodes.getLength(), 0);
-        }
-    };
-
-    struct ConstEntryIteratorAdapter final {
-        const HashMap& map;
+    template<typename R>
+    static R& access(R& node) {
+        return node;
+    }
 
-        ConstEntryIterator begin() const {
-            return ConstEntryIterator(map.nodes, 0, 0);
-        }
+    template<typename I, typename R>
+    static R& accessValue(I& node) {
+        return node.value;
+    }
 
-        ConstEntryIterator end() const {
-            return ConstEntryIterator(map.nodes, map.nodes.getLength(), 0);
-        }
-    };
+    static const K& accessKey(const Node& node) {
+        return node.getKey();
+    }
 
     template<typename N, typename R>
-    class BaseValueIterator final {
-        N& nodes;
-        int indexA;
-        int indexB;
+    using BaseEntryIterator = Iterator<N, R, R, access<R>>;
+    using EntryIterator = BaseEntryIterator<Nodes, Node>;
+    using ConstEntryIterator = BaseEntryIterator<const Nodes, const Node>;
 
-    public:
-        BaseValueIterator(N& nodes, int indexA, int indexB)
-            : nodes(nodes), indexA(indexA), indexB(indexB) {
-            skip();
-        }
+    template<typename N, typename I, typename R>
+    using BaseValueIterator = Iterator<N, I, R, accessValue<I, R>>;
+    using ValueIterator = BaseValueIterator<Nodes, Node, V>;
+    using ConstValueIterator =
+        BaseValueIterator<const Nodes, const Node, const V>;
 
-        BaseValueIterator& operator++() {
-            indexB++;
-            skip();
-            return *this;
-        }
+    using ConstKeyIterator =
+        Iterator<const Nodes, const Node, const K, accessKey>;
 
-        bool operator!=(const BaseValueIterator& other) const {
-            return indexA != other.indexA || indexB != other.indexB;
-        }
+    template<typename M, typename I>
+    struct IteratorAdapter final {
+        M& map;
 
-        R& operator*() {
-            return nodes[indexA][indexB].value;
+        I begin() const {
+            return I(map.nodes, 0, 0);
         }
 
-    private:
-        void skip() {
-            while(indexA < nodes.getLength() &&
-                  indexB >= nodes[indexA].getLength()) {
-                indexA++;
-                indexB = 0;
-            }
+        I end() const {
+            return I(map.nodes, map.nodes.getLength(), 0);
         }
     };
 
-    typedef BaseValueIterator<List<List<Node>>, V> ValueIterator;
-    typedef BaseValueIterator<const List<List<Node>>, const V>
-        ConstValueIterator;
+    using EntryIteratorAdapter = IteratorAdapter<HashMap, EntryIterator>;
+    using ConstEntryIteratorAdapter =
+        IteratorAdapter<const HashMap, ConstEntryIterator>;
 
-    struct ValueIteratorAdapter final {
-        HashMap& map;
+    using ValueIteratorAdapter = IteratorAdapter<HashMap, ValueIterator>;
+    using ConstValueIteratorAdapter =
+        IteratorAdapter<const HashMap, ConstValueIterator>;
 
-        ValueIterator begin() {
-            return ValueIterator(map.nodes, 0, 0);
-        }
-
-        ValueIterator end() {
-            return ValueIterator(map.nodes, map.nodes.getLength(), 0);
-        }
-    };
-
-    struct ConstValueIteratorAdapter final {
-        const HashMap& map;
-
-        ConstValueIterator begin() const {
-            return ConstValueIterator(map.nodes, 0, 0);
-        }
-
-        ConstValueIterator end() const {
-            return ConstValueIterator(map.nodes, map.nodes.getLength(), 0);
-        }
-    };
-
-    class ConstKeyIterator final {
-        const List<List<Node>>& nodes;
-        int indexA;
-        int indexB;
-
-    public:
-        ConstKeyIterator(const List<List<Node>>& nodes, int indexA, int indexB)
-            : nodes(nodes), indexA(indexA), indexB(indexB) {
-            skip();
-        }
-
-        ConstKeyIterator& operator++() {
-            indexB++;
-            skip();
-            return *this;
-        }
-
-        bool operator!=(const ConstKeyIterator& other) const {
-            return indexA != other.indexA || indexB != other.indexB;
-        }
-
-        const K& operator*() {
-            return nodes[indexA][indexB].getKey();
-        }
-
-    private:
-        void skip() {
-            while(indexA < nodes.getLength() &&
-                  indexB >= nodes[indexA].getLength()) {
-                indexA++;
-                indexB = 0;
-            }
-        }
-    };
-
-    struct ConstKeyIteratorAdapter final {
-        const HashMap& map;
-
-        ConstKeyIterator begin() const {
-            return ConstKeyIterator(map.nodes, 0, 0);
-        }
-
-        ConstKeyIterator end() const {
-            return ConstKeyIterator(map.nodes, map.nodes.getLength(), 0);
-        }
-    };
+    using ConstKeyIteratorAdapter =
+        IteratorAdapter<const HashMap, ConstKeyIterator>;
 
 private:
-    List<List<Node>> nodes;
+    Nodes nodes;
     int elements;
 
 public:
@@ -233,28 +138,16 @@ public:
         return true;
     }
 
-    HashMap& add(const K& key, const V& value) {
-        rehash();
-        Hash h = hash(key);
-        V* v = searchList(key, h);
-        if(v == nullptr) {
-            nodes[h].add(key, value);
-            elements++;
-        } else {
-            *v = value;
-        }
-        return *this;
-    }
-
-    HashMap& add(const K& key, V&& value) {
+    template<typename VA>
+    HashMap& add(const K& key, VA&& value) {
         rehash();
         Hash h = hash(key);
         V* v = searchList(key, h);
         if(v == nullptr) {
-            nodes[h].add(key, std::move(value));
+            nodes[h].add(key, std::forward<VA>(value));
             elements++;
         } else {
-            *v = std::move(value);
+            *v = std::forward<VA>(value);
         }
         return *this;
     }
@@ -294,11 +187,11 @@ public:
         return {*this};
     }
 
-    const ConstEntryIteratorAdapter entries() const {
+    ConstEntryIteratorAdapter entries() const {
         return {*this};
     }
 
-    const ConstKeyIteratorAdapter keys() const {
+    ConstKeyIteratorAdapter keys() const {
         return {*this};
     }
 
@@ -306,7 +199,7 @@ public:
         return {*this};
     }
 
-    const ConstValueIteratorAdapter values() const {
+    ConstValueIteratorAdapter values() const {
         return {*this};
     }
 

+ 0 - 12
data/List.h

@@ -107,18 +107,6 @@ public:
         }
     }
 
-    List& add(const T& t) {
-        ensureCapacity();
-        new(data + length++) T(t);
-        return *this;
-    }
-
-    List& add(T&& t) {
-        ensureCapacity();
-        new(data + length++) T(std::move(t));
-        return *this;
-    }
-
     template<typename... Args>
     List& add(Args&&... args) {
         ensureCapacity();

+ 1 - 11
data/Stack.h

@@ -3,21 +3,11 @@
 
 #include "data/List.h"
 
-template<typename T, int N>
+template<typename T>
 class Stack final {
     List<T> data;
 
 public:
-    Stack& push(const T& t) {
-        data.add(t);
-        return *this;
-    }
-
-    Stack& push(T&& t) {
-        data.add(std::move(t));
-        return *this;
-    }
-
     template<typename... Args>
     Stack& push(Args&&... args) {
         data.add(std::forward<Args>(args)...);

+ 0 - 1
tests/HashMapTests.cpp

@@ -7,7 +7,6 @@ typedef HashMap<int, int> IntMap;
 typedef StringBuffer<50> String;
 
 static void testAdd(Test& test) {
-    (void)test;
     IntMap map;
     map.add(5, 4);
     int* value = map.search(5);

+ 1 - 1
tests/StackTests.cpp

@@ -3,7 +3,7 @@
 #include "tests/Test.h"
 #include "utils/StringBuffer.h"
 
-typedef Stack<int, 10> IntStack;
+typedef Stack<int> IntStack;
 typedef StringBuffer<50> String;
 
 static void testPushPopPeek(Test& test) {