stator
A math, geometry, and utility library
stack_vector.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2017 Marcus N Campbell Bannerman <[email protected]>
3 
4  This file is part of stator.
5 
6  stator is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  stator is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with stator. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #pragma once
21 
22 // C++
23 #include <array>
24 #include <ostream>
25 
26 namespace stator {
27  namespace orphan {
43  template<class T, size_t Nmax>
44  class StackVector: public std::array<T, Nmax> {
45  typedef std::array<T, Nmax> Base;
46  public:
47 
50  template<size_t Nmax2,
51  typename = typename std::enable_if<(Nmax2 <= Nmax)>::type>
53  _size(vec.size())
54  { std::copy(vec.begin(), vec.end(), Base::begin()); }
55 
57  StackVector(): Base(), _size(0) {}
58 
60  StackVector(std::initializer_list<T> _list):
61  Base(),
62  _size(0)
63  {
64  auto it = _list.begin();
65  for (size_t i(0); (i < Nmax) && (it != _list.end()); ++i, ++it)
66  push_back(*it);
67  }
68 
70  constexpr typename Base::size_type size() const { return _size; }
71 
73  constexpr bool empty() const { return size() == 0; }
74 
76  typename Base::iterator end() { return Base::begin() + _size; }
77 
79  typename Base::const_iterator end() const { return Base::begin() + _size; }
80 
82  typename Base::const_iterator cend() const { return Base::begin()+ _size; }
83 
86  typename Base::reverse_iterator rbegin() { return typename Base::reverse_iterator(this->end()); }
87 
90  typename Base::const_reverse_iterator rbegin() const { return typename Base::const_reverse_iterator(this->end()); }
91 
94  typename Base::const_reverse_iterator crbegin() const { return typename Base::const_reverse_iterator(this->end()); }
95 
98  typename Base::reverse_iterator rend() { return typename Base::reverse_iterator(this->begin()); }
99 
102  typename Base::const_reverse_iterator rend() const { return typename Base::const_reverse_iterator(this->begin()); }
103 
106  typename Base::const_reverse_iterator crend() const { return typename Base::const_reverse_iterator(this->begin()); }
107 
109  typename Base::reference back() { return _size ? *(this->end() - 1) : *this->end(); }
110 
112  typename Base::const_reference back() const { return _size ? *(this->end() - 1) : *this->end(); }
113 
115  void push_back(const T& val) {
116 #ifdef STATOR_DEBUG
117  if (_size+1 > Nmax)
118  stator_throw() << "Cannot push elements to a filled StackVector " << *this;
119 #endif
120  Base::operator[](_size) = val;
121  ++_size;
122  }
123 
125  T pop_back() {
126 #ifdef STATOR_DEBUG
127  if (empty())
128  stator_throw() << "Cannot pop elements from an empty StackVector " << *this;
129 #endif
130  return Base::operator[](--_size);
131  }
132 
134  template<size_t Nmax2>
135  void extend(const StackVector<T,Nmax2>& ovec) {
136  for (const T& a: ovec)
137  push_back(a);
138  }
139 
140  private:
142  size_t _size;
143  };
144 
146  template<class T, size_t Nmax>
147  std::ostream& operator<<(std::ostream& os, const StackVector<T,Nmax>&s) {
148  os << "StackVector{ ";
149  for (const auto& val : s)
150  os << val << " ";
151  os << "}";
152  return os;
153  }
154 
156  template<class T1, class T2, size_t Nmax>
157  std::ostream& operator<<(std::ostream& os, const StackVector<std::pair<T1,T2>,Nmax>&s) {
158  os << "StackVector{ ";
159  for (const auto& val : s)
160  os << "[" << val.first << ", " << val.second << "] ";
161  os << "}";
162  return os;
163  }
164 
165  namespace detail {
166  template<std::size_t I = 0, typename... Tp>
167  inline typename std::enable_if<I == sizeof...(Tp), void>::type
168  tuple_print(const std::tuple<Tp...>& t, std::ostream& os)
169  { }
170 
171  template<std::size_t I = 0, typename... Tp>
172  inline typename std::enable_if<I < sizeof...(Tp), void>::type
173  tuple_print(const std::tuple<Tp...>& t, std::ostream& os)
174  {
175  os << std::get<I>(t) << " ";
176  tuple_print<I + 1, Tp...>(t, os);
177  }
178  }// namespace detail
179 
181  template<size_t Nmax, typename... Tp>
182  std::ostream& operator<<(std::ostream& os, const StackVector<std::tuple<Tp...>,Nmax>&s)
183  {
184  os << "StackVector{ ";
185  for (const auto& val : s) {
186  os << "[";
187  detail::tuple_print(val, os);
188  os << "] ";
189  }
190  os << "}";
191  return os;
192  }
193  }// namespace orphan
194 }// namespace stator
Base::iterator end()
Returns an iterator pointing to the end of the container.
StackVector(std::initializer_list< T > _list)
Array initialisation constructor.
Base::reverse_iterator rbegin()
Returns a reverse iterator pointing to the start of the container.
Base::const_reverse_iterator rend() const
Returns a reverse iterator pointing to the end of the container.
Stack-allocated equivalent of std::vector.
T pop_back()
Removes and returns the last element of the container.
std::enable_if< I==sizeof...(Tp), void >::type tuple_print(const std::tuple< Tp... > &t, std::ostream &os)
StackVector()
Default constructor.
std::ostream & operator<<(std::ostream &os, const StackVector< T, Nmax > &s)
constexpr bool empty() const
Test if the container is empty.
void push_back(const T &val)
Add an element to the end of the container.
Base::const_reverse_iterator rbegin() const
Returns a reverse iterator pointing to the start of the container.
Base::reverse_iterator rend()
Returns a reverse iterator pointing to the end of the container.
Base::const_iterator cend() const
Returns a const iterator pointing to the end of the container.
Base::const_reverse_iterator crend() const
Returns a const reverse iterator pointing to the end of the container.
constexpr Base::size_type size() const
The number of elements currently stored.
StackVector(const StackVector< T, Nmax2 > &vec)
Copy constructor which allows construction from smaller StackVector types.
The stator library namespace.
Definition: frontpage.dox:243
#define stator_throw()
Definition: exception.hpp:26
Base::reference back()
Returns a reference to the last element stored in the container.
void extend(const StackVector< T, Nmax2 > &ovec)
Merge the contents of another StackVector into this one.
Base::const_iterator end() const
Returns an iterator pointing to the end of the container.
Base::const_reverse_iterator crbegin() const
Returns a const reverse iterator pointing to the start of the container.
Base::const_reference back() const
Returns a reference to the last element stored in the container.