stack.h
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #if !defined(INCLUDED_CONTAINER_STACK_H)
00023 #define INCLUDED_CONTAINER_STACK_H
00024
00025 #include "memory/allocator.h"
00026 #include <algorithm>
00027
00036 template<typename Type>
00037 class Stack: public DefaultAllocator<Type>
00038 {
00039 typedef DefaultAllocator<Type> Allocator;
00040
00041 enum
00042 {
00043 DEFAULT_CAPACITY = 4,
00044 };
00045
00046 typedef Type* pointer;
00047 typedef const Type* const_pointer;
00048
00049 public:
00050 typedef const_pointer const_iterator;
00051 private:
00052
00053 pointer m_data;
00054 pointer m_end;
00055 std::size_t m_capacity;
00056
00057 void insert (const Type& value)
00058 {
00059 Allocator::construct(m_end++, value);
00060 }
00061 void insert_overflow (const Type& value)
00062 {
00063 const std::size_t new_capacity = (m_capacity) ? m_capacity + m_capacity : std::size_t(DEFAULT_CAPACITY);
00064 const pointer new_data = Allocator::allocate(new_capacity);
00065 const pointer new_end = std::copy(m_data, m_end, new_data);
00066
00067 destroy();
00068 Allocator::deallocate(m_data, m_capacity);
00069
00070 m_capacity = new_capacity;
00071 m_data = new_data;
00072 m_end = new_end;
00073 insert(value);
00074 }
00075 void destroy ()
00076 {
00077 for (pointer p = m_data; p != m_end; ++p) {
00078 Allocator::destroy(p);
00079 }
00080 }
00081 void construct (const Stack& other)
00082 {
00083 pointer p = m_data;
00084 for (const_iterator i = other.begin(); i != other.end(); ++i) {
00085 Allocator::construct(p++, *i);
00086 }
00087 }
00088
00089 public:
00090
00091 Stack () :
00092 m_data(0), m_end(0), m_capacity(0)
00093 {
00094 }
00095 Stack (const Type& value) :
00096 m_data(0), m_end(0), m_capacity(0)
00097 {
00098 push(value);
00099 }
00100 Stack (const Stack& other) :
00101 DefaultAllocator<Type> (other)
00102 {
00103 m_capacity = other.m_capacity;
00104 m_data = Allocator::allocate(m_capacity);
00105 construct(other);
00106 m_end = m_data + other.size();
00107 }
00108 ~Stack ()
00109 {
00110 destroy();
00111 Allocator::deallocate(m_data, m_capacity);
00112 }
00113
00114 const_iterator begin () const
00115 {
00116 return m_data;
00117 }
00118 const_iterator end () const
00119 {
00120 return m_end;
00121 }
00122
00123 bool empty () const
00124 {
00125 return end() == begin();
00126 }
00127 void clear ()
00128 {
00129 destroy();
00130 m_end = m_data;
00131 }
00132
00133 std::size_t size () const
00134 {
00135 return m_end - m_data;
00136 }
00137 Type operator[] (const std::size_t i) const
00138 {
00139 return m_data[i];
00140 }
00142 void push (const Type& value)
00143 {
00144 if (size() == m_capacity) {
00145 insert_overflow(value);
00146 } else {
00147 insert(value);
00148 }
00149 }
00151 void pop ()
00152 {
00153 Allocator::destroy(--m_end);
00154 }
00156 Type& top ()
00157 {
00158 return *(m_end - 1);
00159 }
00161 const Type& top () const
00162 {
00163 return *(m_end - 1);
00164 }
00166 Type& parent ()
00167 {
00168 return *(m_end - 2);
00169 }
00171 const Type& parent () const
00172 {
00173 return *(m_end - 2);
00174 }
00176 void swap (Stack& other)
00177 {
00178 std::swap(m_data, other.m_data);
00179 std::swap(m_end, other.m_end);
00180 std::swap(m_capacity, other.m_capacity);
00181 }
00182 #if 1 // use copy-swap technique
00183 Stack& operator= (const Stack& other)
00184 {
00185 Stack temp(other);
00186 temp.swap(*this);
00187 return *this;
00188 }
00189 #else // avoids memory allocation if capacity is already sufficient.
00190 Stack& operator=(const Stack& other) {
00191 if (&other != this) {
00192 destroy();
00193
00194 if (other.size() > m_capacity) {
00195 Allocator::deallocate(m_data, m_capacity);
00196 m_capacity = other.m_capacity;
00197 m_data = Allocator::allocate(m_capacity);
00198 }
00199 m_end = m_data + other.size();
00200
00201 construct(other);
00202 }
00203 return *this;
00204 }
00205 #endif
00206 };
00207
00209 template<typename Type>
00210 inline bool operator< (const Stack<Type>& self, const Stack<Type>& other)
00211 {
00212 return std::lexicographical_compare(self.begin(), self.end(), other.begin(), other.end());
00213 }
00214
00215 namespace std
00216 {
00219 template<typename Type>
00220 inline void swap (Stack<Type>& self, Stack<Type>& other)
00221 {
00222 self.swap(other);
00223 }
00224 }
00225
00226 #endif