2 * Implementation of a Generic Data Structure Container Template including STL Iterator
3 * Copyright (c) 2014 TJ <hacker@iam.tj>
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 * see ./COPYRIGHT or http://www.gnu.org/licenses/gpl-3.0.html
20 #ifndef _GENERICSTORAGECONTAINERTEMPLATEIMPL_HPP_
21 #define _GENERICSTORAGECONTAINERTEMPLATEIMPL_HPP_
23 #include "DataStructures.hpp"
30 /* A generic Container that can use different internal data structures
31 * (Array, Linked-List, Binary Search Tree) determined by
32 * application code at compile time using the power of Templating
33 * and Metaprogramming of C++11 and later.
35 * Default data structure is a Dynamic Array
37 * Uses Metaprogramming conditionals to create constant and non-constant iterators
38 * from a single iterator definition. Provides typedefs to make instantiating the
39 * correct type of iterator easier to read and write in application code.
42 template <typename T, template<typename> class DATA_STRUCTURE = DataStructure_ArrayDynamic>
43 class GenericStorageContainerTemplateImpl
47 // data structure type is templated
48 DATA_STRUCTURE<T> data_structure_;
53 /* constant and non-constant custom Standard Template Library (STL) compatible iterators
54 * avoiding writing 2 separate class definitions that only differ on their
55 * constant vs non-constant type specifiers. This makes extensive use of
56 * template metaprogramming
58 * defaults to a non-const iterator
60 template <bool is_const_iterator = false>
61 class iterator : public std::iterator< std::bidirectional_iterator_tag, AbstractDataStructure<T> >
63 typedef iterator self_type;
64 typedef typename std::conditional< is_const_iterator, const AbstractDataStructure<T>, AbstractDataStructure<T> >::type value_type;
65 typedef typename std::conditional< is_const_iterator, const AbstractDataStructure<T>&, AbstractDataStructure<T>& >::type reference;
66 typedef typename std::conditional< is_const_iterator, const AbstractDataStructure<T>*, AbstractDataStructure<T>* >::type pointer;
67 typedef std::bidirectional_iterator_tag iterator_category;
68 typedef int difference_type;
70 DATA_STRUCTURE<T>* element_;
74 iterator<is_const_iterator> () {};
75 iterator<is_const_iterator> (DATA_STRUCTURE<T>* element) : element_(element) {};
76 iterator<is_const_iterator> (const iterator<is_const_iterator>& copy) : element_(copy.element_) {}; // copy constructor
78 // ForwardIterator methods
80 // postfix increment operator
81 self_type operator++()
83 self_type original(*this); // need to keep a copy of the current value so it can be returned
85 DATA_STRUCTURE<T>* temp = element_->get_next();
87 element_ = temp; // the increment changes the item being referenced
92 // prefix increment operator
93 self_type operator++(int unused)
95 DATA_STRUCTURE<T>* result = nullptr;
98 result = element_->get_next();
104 // BidirectionalIterator methods
107 self_type operator--()
109 self_type original(*this); // keep copy that is to be returned
110 this->element_->get_previous();
115 self_type operator--(int unused)
118 element_ = element_->get_previous();
123 // comparison methods
124 bool operator==(const self_type& right_hand_side)
128 if (element_ && right_hand_side.element_)
129 result = *this->element_ == *right_hand_side.element_;
134 bool operator!=(const self_type& right_hand_side)
136 return !this->operator==(right_hand_side);
139 bool operator<(const self_type& right_hand_side)
143 if (element_ && right_hand_side.element_)
144 result = *this->element_ < *right_hand_side.element_;
149 bool operator<=(const self_type& right_hand_side)
151 return this->operator==(right_hand_side) | this->operator<(right_hand_side);
158 return element_ ? *element_->get_data() : 0;
161 std::conditional<is_const_iterator, const T*, T*> operator->()
163 return &element_->get_data();
166 // allow const and non-const iterator copy-contructors access to private members
167 friend class iterator<!is_const_iterator>;
169 }; // end of Iterator
171 // use these handy short-cuts in application code
172 typedef iterator<true> _const_iterator;
173 typedef iterator<false> _iterator;
175 /* methods directly supporting use of the iterator uses 'template' to avoid
176 * writing 4 method definitions (2 for constant and 2 for non-constant iterators)
178 * begin() and end() are used in code that instantiates the iterator:
180 * GSCTI<int> container;
181 * container.insert(1);
182 * container.insert(2);
184 * for (_const_iterator i = container.begin(); i != container.end(); ++i)
186 * cout << *i << endl;
189 * for (auto element : container ) // range-for operator
191 * cout << element << endl;
194 template<bool is_const_iterator = false>
195 iterator<is_const_iterator> begin()
197 return iterator<is_const_iterator>(data_structure_.get_begin());
200 template<bool is_const_iterator = false>
201 iterator<is_const_iterator> end()
203 return iterator<is_const_iterator>(data_structure_.get_end());
207 GenericStorageContainerTemplateImpl<T, DATA_STRUCTURE> () {};
208 GenericStorageContainerTemplateImpl<T, DATA_STRUCTURE> (const GenericStorageContainerTemplateImpl<T, DATA_STRUCTURE>& copy)
210 // TODO: implement copy constructor
213 ~GenericStorageContainerTemplateImpl<T, DATA_STRUCTURE>()
218 size_t get_capacity()
220 return data_structure_.get_capacity();
225 return data_structure_.get_size();
233 return data_structure_.append(data);
242 }; // end of GenericStorageContainerTemplateImpl
244 // handy short-cuts for unweildy names
245 template<typename T, template<class> class DS = DataStructure_ArrayDynamic> using GSCTI = GenericStorageContainerTemplateImpl< T, DS>;
247 }; // end of namespace