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 /* A generic Container that can use different internal storage
30 * representations (Array, Linked-List, Binary Search Tree) based on an
31 * enum passed by application code at compile time using the power of Templating
32 * and Metaprogramming of C++11 and later.
34 * Uses Metaprogramming conditionals to create constant and non-constant iterators
35 * from a single iterator definition. Provides typedefs to make instantiating the
36 * correct type of iterator easier to read and write in application code.
39 template <typename T, template<typename> class STORAGE_CLASS = StorageClass_DynamicArray>
40 class GenericStorageContainerTemplateImpl
42 /* XXX: Have to use different template typename value (T, S, etc.) although the types are
43 * the same else the compiler cannot determine the correct value to use.
44 * Metaprogramming does not have the concept of scope or namespace:
47 * GenericStorageContainerTemplateImpl.hpp:40:15: error: declaration of ‘class T’
48 * template <typename T>
50 * GenericStorageContainerTemplateImpl.hpp:31:13: error: shadows template parm ‘class T’
51 * template <typename T, int storage_class>
57 // storage class type is templated
58 STORAGE_CLASS<T> storage_;
63 GenericStorageContainerTemplateImpl() {};
64 GenericStorageContainerTemplateImpl(const GenericStorageContainerTemplateImpl<T, STORAGE_CLASS>& copy)
68 ~GenericStorageContainerTemplateImpl()
73 /* constant and non-constant custom Standard Template Library (STL) iterators
74 * avoiding writing 2 separate class definitions that only differ on their
75 * constant vs non-constant type specifiers. This makes extensive use of
76 * template metaprogramming
78 * defaults to a non-const iterator
80 template <bool is_const_iterator = false>
81 class iterator : public std::iterator< std::bidirectional_iterator_tag, StorageClass<T> >
83 /* XXX: Ensure the <iterator> header is included to avoid cryptic errors:
85 * GenericStorageContainerTemplateImpl.hpp:168:42: error: expected template-name before ‘<’ token
86 * class iterator : public std::iterator< std::bidirectional_iterator_tag, StorageClass<T> >
88 * GenericStorageContainerTemplateImpl.hpp:168:42: error: expected ‘{’ before ‘<’ token
89 * GenericStorageContainerTemplateImpl.hpp:168:42: error: expected unqualified-id before ‘<’ token
93 * 1. typedef the container's type to the naming convention used by the STL iterators (makes readable code)
94 * 2. Use Metaprogramming's std::conditional to decide whether to declare const or non-const iterator
95 * which avoids writing 2 iterator classes, keeping the code cleaner and easier to use
96 * 3. declare and implement methods to support forward and reverse iteration (bidirectional)
98 typedef iterator self_type;
99 typedef typename std::conditional< is_const_iterator, const StorageClass<T>, StorageClass<T> >::type value_type;
100 typedef typename std::conditional< is_const_iterator, const StorageClass<T>&, StorageClass<T>& >::type reference;
101 typedef typename std::conditional< is_const_iterator, const StorageClass<T>*, StorageClass<T>* >::type pointer;
102 typedef std::bidirectional_iterator_tag iterator_category;
103 typedef int difference_type;
105 StorageClass<T>& __node;
109 iterator<is_const_iterator> () {}; // default constructor
110 iterator<is_const_iterator> ( StorageClass<T>& node) : __node(node) {};
111 iterator<is_const_iterator> (const iterator<is_const_iterator>& copy) : __node(copy.__node) {}; // copy constructor
113 // ForwardIterator methods
115 // postfix increment operator
116 self_type operator++()
118 self_type original = *this; // need to keep a reference to the current value so it can be returned
119 this->__node = this->__node->get_next(); // after the increment changes the item being referenced
123 // prefix increment operator
124 self_type operator++(int unused)
126 __node = __node.get_next();
130 // BidirectionalIterator methods
133 self_type operator--()
135 self_type original = *this; // keep reference to value that is to be returned
136 this->__node.get_previous();
141 self_type operator--(int unused)
143 __node = __node->get_previous();
147 // Comparison methods
148 bool operator==(const self_type& right_hand_side)
150 return __node == right_hand_side.__node;
153 bool operator!=(const self_type& right_hand_side)
155 return __node != right_hand_side.__node;
160 return __node->get_data();
163 std::conditional<is_const_iterator, const T*, T*> operator->()
165 return &__node->get_data();
168 // allow const and non-const iterator copy-contructors access to private members
169 friend class iterator<!is_const_iterator>;
171 }; // end of Iterator
173 // use these handy short-cuts in application code
174 typedef iterator<true> _const_iterator;
175 typedef iterator<false> _iterator;
177 }; // end of GenericStorageContainerTemplateImpl
179 // handy short-cuts for unweildy names
180 template<typename T, template<class> class SC = StorageClass_DynamicArray> using GSCTI = GenericStorageContainerTemplateImpl< T, SC>;
182 }; // end of namespace