/*
- * 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
* 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>
* 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
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
+