Use descriptive enums for method parameters
[GenericStorageContainerTemplate.git] / GenericStorageContainerTemplateImpl.hpp
index e75fc00..e63ff21 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Implementation of a Generic Storage Type Container Template including STL Iterator
+ * Implementation of a Generic Data Structure Container Template including STL Iterator
  * Copyright (c) 2014 TJ <hacker@iam.tj>
  *
  *    This program is free software: you can redistribute it and/or modify
@@ -17,8 +17,8 @@
  * see ./COPYRIGHT or http://www.gnu.org/licenses/gpl-3.0.html
  */
 
-#ifndef _GENERIC_STORAGE_CONTAINER_TEMPLATE_IMPL_HPP_
-#define _GENERIC_STORAGE_CONTAINER_TEMPLATE_IMPL_HPP_
+#ifndef _GENERICSTORAGECONTAINERTEMPLATEIMPL_HPP_
+#define _GENERICSTORAGECONTAINERTEMPLATEIMPL_HPP_
 
 #include "DataStructures.hpp"
 #include <iterator>
@@ -38,28 +38,24 @@ namespace tj
    * from a single iterator definition. Provides typedefs to make instantiating the
    * correct type of iterator easier to read and write in application code.
    *
+   * template parameters:
+   * T = type being stored
+   * DATA_STRUCTURE = class providing underlying storage of T elements, defaults to dynamic array
+   *
+   * For template template parameters see http://en.cppreference.com/w/cpp/language/template_parameters
    */
   template <typename T, template<typename> class DATA_STRUCTURE = DataStructure_ArrayDynamic>
   class GenericStorageContainerTemplateImpl
   {
-    // attributes
-    
-    // data structure type is templated
+    // easy to read aliases
+    typedef AbstractDataStructure<T> DS_BASE_CLASS; // for access to enums
+
+    // data structure type is templated and decided by application code at compilation time
     DATA_STRUCTURE<T> data_structure_;
 
 
     public:
 
-    GenericStorageContainerTemplateImpl() {};
-    GenericStorageContainerTemplateImpl(const GenericStorageContainerTemplateImpl<T, DATA_STRUCTURE>& copy)
-    {
-
-    };
-    ~GenericStorageContainerTemplateImpl()
-    {
-      delete data_structure_;
-    };
-
     /* constant and non-constant custom Standard Template Library (STL) compatible iterators
      * avoiding writing 2 separate class definitions that only differ on their
      * constant vs non-constant type specifiers. This makes extensive use of
@@ -77,83 +73,197 @@ namespace tj
       typedef std::bidirectional_iterator_tag iterator_category;
       typedef int difference_type;
 
-      AbstractDataStructure<T>& element_;
+      DATA_STRUCTURE<T>* element_;
 
       public:
 
       iterator<is_const_iterator> () {};
-      iterator<is_const_iterator> (AbstractDataStructure<T>& element) : element_(element) {};
+      iterator<is_const_iterator> (DATA_STRUCTURE<T>* element) : element_(element) {};
       iterator<is_const_iterator> (const iterator<is_const_iterator>& copy) : element_(copy.element_) {}; // copy constructor
 
-      // ForwardIterator methods
+      /* ForwardIterator methods */
 
       // postfix increment operator
       self_type operator++()
       {
-        self_type original = *this; // need to keep a copy of the current value so it can be returned
-        this->element_ = this->element_.get_next(); // after the increment changes the item being referenced
+        self_type original(*this); // need to keep a copy of the current value so it can be returned
+
+        DATA_STRUCTURE<T>* temp = element_->get_next();
+        if (temp)
+          element_ = temp; // the increment changes the item being referenced
+
         return original;
-      }
+      };
 
       // prefix increment operator
       self_type operator++(int unused)
       {
-        element_ = element_.get_next();
+        DATA_STRUCTURE<T>* result = nullptr;
+
+        if (element_) {
+          result = element_->get_next();
+          element_ = result;
+        }
         return *this;
-      }
+      };
 
-      // BidirectionalIterator methods
+      /* BidirectionalIterator methods */
 
       // postfix decrement
       self_type operator--()
       {
-        self_type original = *this; // keep reference to value that is to be returned
-        this->element_.get_previous();
+        self_type original(*this); // keep copy that is to be returned
+        this->element_->get_previous();
         return original;
       };
 
       // prefix decrement
       self_type operator--(int unused)
       {
-        element_ = element_.get_previous();
+        if (element_)
+          element_ = element_->get_previous();
+
         return *this;
       };
 
-      // Comparison methods
+
+      /* Comparison */
+
       bool operator==(const self_type& right_hand_side)
       {
-        return element_ == right_hand_side.element_; 
-      }
+        bool result = false;
 
+        if (element_ && right_hand_side.element_)
+          result = *this->element_ == *right_hand_side.element_; 
+
+        return result;
+      };
+
+      // implemented using operator==()
       bool operator!=(const self_type& right_hand_side)
       {
-        return element_ != right_hand_side.element_;
-      }
+        return !this->operator==(right_hand_side);
+      };
+
+      bool operator<(const self_type& right_hand_side)
+      {
+        bool result = false;
+
+        if (element_ && right_hand_side.element_)
+          result = *this->element_ < *right_hand_side.element_;
+
+        return result;
+      };
+
+      // implemented using operator==() and operator<()
+      bool operator<=(const self_type& right_hand_side)
+      {
+        return this->operator==(right_hand_side) | this->operator<(right_hand_side);
+      };
 
+      /* 
+       * Data access */
+
+      // value-at
       T operator* ()
       {
-        return element_.get_data();
-      }
+        return element_ ? *element_->get_data() : 0;
+      };
 
+      // pointer-to
       std::conditional<is_const_iterator, const T*, T*>  operator->()
       { 
-        return &element_.get_data();
-      }
+        return &element_->get_data();
+      };
 
-      // allow const and non-const iterator copy-contructors access to private members 
+      // allow const and non-const iterator copy-contructors access to private members of each other
       friend class iterator<!is_const_iterator>;
 
     }; // end of Iterator
 
-  // use these handy short-cuts in application code
-  typedef iterator<true> _const_iterator;
-  typedef iterator<false> _iterator;
+    // use these handy aliases in application code
+    typedef iterator<true> _const_iterator;
+    typedef iterator<false> _iterator;
+
+    /* methods directly supporting use of the iterator uses 'template' to avoid
+     * writing 4 method definitions (2 for constant and 2 for non-constant iterators)
+     *
+     * begin() and end() are used in code that instantiates the iterator:
+     *
+     * GSCTI<int> container;
+     * container.append(1);
+     * container.append(2);
+     *
+     * for (_const_iterator i = container.begin(); i != container.end(); ++i) 
+     * {
+     *   cout << *i << endl;
+     * }
+     *
+     * for (auto element : container ) // range-for operator
+     * { 
+     *   cout << element << endl;
+     * }
+     */
+    template<bool is_const_iterator = false>
+    iterator<is_const_iterator> begin()
+    { 
+      return iterator<is_const_iterator>(data_structure_.get_begin());
+    };
+
+    template<bool is_const_iterator = false>
+    iterator<is_const_iterator> end()
+    { 
+      return iterator<is_const_iterator>(data_structure_.get_end());
+    };
+
+
+    /* Object life-cycle */
+
+    GenericStorageContainerTemplateImpl<T, DATA_STRUCTURE> () {};
+    GenericStorageContainerTemplateImpl<T, DATA_STRUCTURE> (const GenericStorageContainerTemplateImpl<T, DATA_STRUCTURE>& copy)
+    {
+       // TODO: implement copy constructor
+    };
+
+    ~GenericStorageContainerTemplateImpl<T, DATA_STRUCTURE>()
+    {
+    };
+
+
+    /* Capacity */
+
+    // storage allocated (in units of stored type)
+    size_t get_capacity()
+    {
+      return data_structure_.get_capacity();
+    };
+
+    // storage used (in units of stored type)
+    size_t get_size()
+    {
+      return data_structure_.get_size();
+    };
+
+    /* Modifiers */
+
+    // append
+    bool append(T& data)
+    {
+      return data_structure_.append(data);
+    };
+
+    // remove
+    bool remove()
+    {
+      return data_structure_.remove_at(DS_BASE_CLASS::HEAD, DS_BASE_CLASS::NO_ERASE);
+    };
 
   }; // end of GenericStorageContainerTemplateImpl
 
-  // handy short-cuts for unweildy names
+  // GSCTI: handy alias for unweildy type name
   template<typename T, template<class> class DS = DataStructure_ArrayDynamic> using GSCTI = GenericStorageContainerTemplateImpl< T, DS>;
 
 }; // end of namespace
 
 #endif
+