2 * Implementation of a Generic Storage Type 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 _GENERIC_STORAGE_CONTAINER_TEMPLATE_IMPL_HPP_
21 #define _GENERIC_STORAGE_CONTAINER_TEMPLATE_IMPL_HPP_
29 /* possible options for the storage class the application may request
40 LENGTH // allows application to determine how many storage classes are available
43 /* A generic Container that can use different internal storage
44 * representations (Array, Linked-List, Binary Search Tree) based on an
45 * enum passed by application code at compile time using the power of Templating
46 * and Metaprogramming of C++11 and later.
48 * Uses Metaprogramming conditionals to create constant and non-constant iterators
49 * from a single iterator definition. Provides typedefs to make instantiating the
50 * correct type of iterator easier to read and write in application code.
53 template <typename T, class STORAGE_CLASS>
54 class GenericStorageContainerTemplateImpl
56 /* XXX: Have to use different template typename value (T, S, etc.) although the types are
57 * the same else the compiler cannot determine the correct value to use.
58 * Metaprogramming does not have the concept of scope or namespace:
61 * GenericStorageContainerTemplateImpl.hpp:40:15: error: declaration of ‘class T’
62 * template <typename T>
64 * GenericStorageContainerTemplateImpl.hpp:31:13: error: shadows template parm ‘class T’
65 * template <typename T, int storage_class>
69 /* Abstract base class for the different storage classes
71 * Defines the API they must implement. The API allows the Container and its
72 * Iterator to call common methods to perform store, retrieve, and search operations
83 StorageClass(S& data) : __data(data) {};
84 virtual ~StorageClass() {};
86 /* API available to application
88 * Some methods are pure virtual making this an Abstract (base) class
89 * Sub-classes must implement these methods and over-ride others to
90 * provide the specific storage class functionality
97 virtual S& get_first() = 0;
98 virtual S& get_previous() = 0;
99 virtual S& get_next() = 0;
100 virtual S& get_last() = 0;
103 * @param data the item (of type S) to be stored
104 * @param index position to insert; 0 is 'beginning', -1 is 'end'
106 * Depending on the concrete implemenation of this method, values of index other
107 * than 0 or -1 may have no meaning and be ignored
109 virtual bool insert_at(S& data, long index = -1) = 0;
110 virtual bool insert(S& data)
112 return insert_at(data, 0);
114 virtual bool append(S& data)
116 return insert_at(data, -1);
119 virtual bool remove_at(S& data, long index = -1) = 0;
120 virtual bool remove() = 0;
121 virtual bool remove(S& data) = 0;
122 virtual bool erase(S& data) = 0;
126 /* Specialised storage class implementing a Dynamic Array
128 template <typename SAD>
129 class StorageClass_DynamicArray : StorageClass<SAD>
134 /* Specialised storage class implementing a 2-way Linked List
136 template <typename SLLD>
137 class StorageClass_LinkedListDouble : StorageClass<SLLD>
142 /* Specialised storage class implementing a Binary Search Tree
144 template <typename SBST>
145 class StorageClass_BinarySearchTree : StorageClass<SBST>
153 /* storage class type is decided when collection is compiled
154 * so use the (abstract) base class to keep the Collection's private
155 * reference to the internal storage class
157 STORAGE_CLASS __storage;
162 GenericStorageContainerTemplateImpl() : __storage(nullptr) {};
163 GenericStorageContainerTemplateImpl(T& data)
166 __storage = new STORAGE_CLASS(data);
169 /* constant and non-constant custom Standard Template Library (STL) iterators
170 * avoiding writing 2 separate class definitions that only differ on their
171 * constant vs non-constant type specifiers. This makes extensive use of
172 * template metaprogramming
174 * defaults to a non-const iterator
176 template <bool is_const_iterator = false>
177 class iterator : public std::iterator< std::bidirectional_iterator_tag, StorageClass<T> >
179 /* XXX: Ensure the <iterator> header is included to avoid cryptic errors:
181 * GenericStorageContainerTemplateImpl.hpp:168:42: error: expected template-name before ‘<’ token
182 * class iterator : public std::iterator< std::bidirectional_iterator_tag, StorageClass<T> >
184 * GenericStorageContainerTemplateImpl.hpp:168:42: error: expected ‘{’ before ‘<’ token
185 * GenericStorageContainerTemplateImpl.hpp:168:42: error: expected unqualified-id before ‘<’ token
189 * 1. typedef the container's type to the naming convention used by the STL iterators (makes readable code)
190 * 2. Use Metaprogramming's std::conditional to decide whether to declare const or non-const iterator
191 * which avoids writing 2 iterator classes, keeping the code cleaner and easier to use
192 * 3. declare and implement methods to support forward and reverse iteration (bidirectional)
194 typedef iterator self_type;
195 typedef typename std::conditional< is_const_iterator, const StorageClass<T>, StorageClass<T> >::type value_type;
196 typedef typename std::conditional< is_const_iterator, const StorageClass<T>&, StorageClass<T>& >::type reference;
197 typedef typename std::conditional< is_const_iterator, const StorageClass<T>*, StorageClass<T>* >::type pointer;
198 typedef std::bidirectional_iterator_tag iterator_category;
199 typedef int difference_type;
201 StorageClass<T>& __node;
205 iterator<is_const_iterator> () {}; // default constructor
206 iterator<is_const_iterator> ( StorageClass<T>& node) : __node(node) {};
207 iterator<is_const_iterator> (const iterator<is_const_iterator>& copy) : __node(copy.__node) {}; // copy constructor
209 // ForwardIterator methods
211 // postfix increment operator
212 self_type operator++()
214 self_type original = *this; // need to keep a reference to the current value so it can be returned
215 this->__node = this->__node->get_next(); // after the increment changes the item being referenced
219 // prefix increment operator
220 self_type operator++(int unused)
222 __node = __node.get_next();
226 // BidirectionalIterator methods
229 self_type operator--()
231 self_type original = *this; // keep reference to value that is to be returned
232 this->__node.get_previous();
237 self_type operator--(int unused)
239 __node = __node->get_previous();
243 // Comparison methods
244 bool operator==(const self_type& right_hand_side)
246 return __node == right_hand_side.__node;
249 bool operator!=(const self_type& right_hand_side)
251 return __node != right_hand_side.__node;
256 return __node->get_data();
259 std::conditional<is_const_iterator, const T*, T*> operator->()
261 return &__node->get_data();
264 // allow const and non-const iterator copy-contructors access to private members
265 friend class iterator<!is_const_iterator>;
267 }; // end of Iterator
269 // use these handy short-cuts in application code
270 typedef iterator<true> _const_iterator;
271 typedef iterator<false> _iterator;
273 }; // end of GenericStorageContainerTemplateImpl
275 // handy short-cuts for unweildy names
276 template<typename T, class SC> using GSCTI = GenericStorageContainerTemplateImpl< T, SC>;
277 template<typename T> using SC_DA = tj::GenericStorageContainerTemplateImpl::StorageClass_DynamicArray<T>;
279 }; // end of namespace