Empirical
array.h
Go to the documentation of this file.
1 
19 #ifndef EMP_ARRAY_H
20 #define EMP_ARRAY_H
21 
22 #include <initializer_list>
23 #include <array>
24 
25 #include "assert.h"
26 #include "../meta/TypeID.h"
27 
28 #ifdef EMP_NDEBUG
29 
30 namespace emp {
32  template <typename T, size_t N> using array = std::array<T,N>;
33 }
34 
35 #else
36 
37 namespace emp {
38 
41  template <typename T, size_t N>
42  class array : public std::vector<T> {
43  private:
44  using this_t = emp::array<T,N>;
45  using base_t = std::vector<T>;
46 
47  public:
48  bool valid;
49 
51  template<typename ITERATOR_T>
52  struct iterator_wrapper : public ITERATOR_T {
54  using wrapped_t = ITERATOR_T;
56 
58  const vec_t * v_ptr;
59 
60  iterator_wrapper(const ITERATOR_T & _in, const vec_t * _v) : ITERATOR_T(_in), v_ptr(_v) { ; }
61  iterator_wrapper(const this_t &) = default;
62  iterator_wrapper(this_t &&) = default;
64 
65  // Debug tools to make sure this iterator is okay.
66  bool OK(bool begin_ok=true, bool end_ok=true) const {
67  if (v_ptr == nullptr) return false; // Invalid vector
68  if (!v_ptr->valid) return false; // Vector has been deleted!
69  size_t pos = (size_t) (*this - v_ptr->begin());
70  if (pos > v_ptr->size()) return false; // Iterator out of range.
71  if (!begin_ok && pos == 0) return false; // Iterator not allowed at beginning.
72  if (!end_ok && pos == v_ptr->size()) return false; // Iterator not allowed at end.
73  return true;
74  }
75 
76  this_t & operator=(const this_t &) = default;
77  this_t & operator=(this_t &&) = default;
78 
79  operator ITERATOR_T() { return *this; }
80  operator const ITERATOR_T() const { return *this; }
81 
82  auto & operator*() {
83  emp_assert(OK(true, false)); // Ensure array is being pointed to properly.
84  return wrapped_t::operator*();
85  }
86  const auto & operator*() const {
87  emp_assert(OK(true, false)); // Ensure array is being pointed to properly.
88  return wrapped_t::operator*();
89  }
90 
91  auto operator->() {
92  emp_assert(OK(true, false)); // Ensure array is being pointed to properly.
93  return wrapped_t::operator->();
94  }
95  const auto operator->() const {
96  emp_assert(OK(true, false)); // Ensure array is being pointed to properly.
97  return wrapped_t::operator->();
98  }
99 
100  this_t & operator++() { emp_assert(OK(true,false)); wrapped_t::operator++(); return *this; }
101  this_t operator++(int x) { emp_assert(OK(true,false)); return this_t(wrapped_t::operator++(x), v_ptr); }
102  this_t & operator--() { emp_assert(OK(false,true)); wrapped_t::operator--(); return *this; }
103  this_t operator--(int x) { emp_assert(OK(false,true)); return this_t(wrapped_t::operator--(x), v_ptr); }
104 
105  auto operator+(int in) { emp_assert(OK()); return this_t(wrapped_t::operator+(in), v_ptr); }
106  auto operator-(int in) { emp_assert(OK()); return this_t(wrapped_t::operator-(in), v_ptr); }
107  auto operator-(const this_t & in) { emp_assert(OK()); return ((wrapped_t) *this) - (wrapped_t) in; }
108 
109  this_t & operator+=(int in) { emp_assert(OK()); wrapped_t::operator+=(in); return *this; }
110  this_t & operator-=(int in) { emp_assert(OK()); wrapped_t::operator-=(in); return *this; }
111  auto & operator[](int offset) { emp_assert(OK()); return wrapped_t::operator[](offset); }
112  };
113 
114  using iterator = iterator_wrapper< typename base_t::iterator >;
115  using const_iterator = iterator_wrapper< typename base_t::const_iterator >;
116  using reverse_iterator = iterator_wrapper< typename base_t::reverse_iterator >;
117  using const_reverse_iterator = iterator_wrapper< typename base_t::const_reverse_iterator >;
118  using value_type = T;
119  using size_type = typename base_t::size_type;
120  using reference = typename base_t::reference;
121  using const_reference = typename base_t::const_reference;
122 
123  array() : base_t(N), valid(true) {};
124  array(const this_t & _in) : base_t(_in), valid(true) { emp_assert(_in.size() == N); };
125  array(std::initializer_list<T> in_list) : base_t(in_list), valid(true) { emp_assert(size() == N); }
126  array(const base_t & in) : base_t(in), valid(true) { emp_assert(size() == N); } // Emergency fallback
127  template <typename InputIt>
128  array(InputIt first, InputIt last) : base_t(first, last), valid(true) { emp_assert(size() == N); }
129  ~array() { valid=false; } // No longer valid when array is deleted.
130 
131  operator std::array<T,N>() {
132  std::array<T,N> ar;
133  for (size_t i = 0; i < N; i++) ar[i] = base_t::operator[](i);
134  return ar;
135  }
136 
137  constexpr size_t size() const { return N; }
138 
139  iterator begin() noexcept { return iterator(base_t::begin(), this); }
140  const_iterator begin() const noexcept { return const_iterator(base_t::begin(), this); }
141  iterator end() noexcept { return iterator(base_t::end(), this); }
142  const_iterator end() const noexcept { return const_iterator(base_t::end(), this); }
143 
144  this_t & operator=(const this_t &) = default;
145 
146  T & operator[](size_t pos) {
147  emp_assert(pos < N, pos, N);
148  return base_t::operator[](pos);
149  }
150 
151  const T & operator[](size_t pos) const {
152  emp_assert(pos < N, pos, N);
153  return base_t::operator[](pos);
154  }
155 
156  T & back() { emp_assert(N > 0); return base_t::back(); }
157  const T & back() const { emp_assert(N > 0); return base_t::back(); }
158  T & front() { emp_assert(N > 0); return base_t::front(); }
159  const T & front() const { emp_assert(N > 0); return base_t::front(); }
160 
161  void fill(const T & val) { this->assign(N, val); }
162 
163  // Functions to make sure to throw an error on:
164 
165  void resize(size_t new_size) { emp_assert(false, "invalid operation for array!"); }
166  void resize(size_t new_size, const T & val) { emp_assert(false, "invalid operation for array!"); }
167 
168  template <typename... PB_Ts>
169  void push_back(PB_Ts &&... args) { emp_assert(false, "invalid operation for array!"); }
170  void pop_back() { emp_assert(false, "invalid operation for array!"); }
171 
172  template <typename... ARGS>
173  iterator insert(ARGS &&... args) {
174  emp_assert(false, "invalid operation for array!");
175  return iterator( base_t::insert(std::forward<ARGS>(args)...), this );
176  }
177 
178  template <typename... ARGS>
179  iterator erase(ARGS &&... args) {
180  emp_assert(false, "invalid operation for array!");
181  return iterator( base_t::erase(std::forward<ARGS>(args)...), this );
182  }
183 
184  template <typename... ARGS>
185  iterator emplace(ARGS &&... args) {
186  emp_assert(false, "invalid operation for array!");
187  return iterator( base_t::emplace(std::forward<ARGS>(args)...), this );
188  }
189 
190  template <typename... ARGS>
191  void emplace_back(ARGS &&... args) {
192  emp_assert(false, "invalid operation for array!");
193  }
194  };
195 
196 
197 }
198 
199 // A crude, generic printing function for arrays.
200 template <typename T, size_t N>
201 std::ostream & operator<<(std::ostream & out, const emp::array<T,N> & v) {
202  for (const T & x : v) out << x << " ";
203  return out;
204 }
205 
206 template <typename T, size_t N>
207 std::istream & operator>>(std::istream & is, emp::array<T,N> & v) {
208  for (T & x : v) is >> x;
209  return is;
210 }
211 
212 #endif
213 
214 namespace emp{
216  template <typename T, size_t N> struct TypeID<emp::array<T,N>> {
217  static std::string GetName() {
218  std::stringstream ss;
219  ss << "emp::array<" << TypeID<T>::GetName() << "," << N << ">";
220  return ss.str();
221  }
222  };
223 }
224 
225 #endif
this_t operator--(int x)
Definition: array.h:103
auto operator-(const this_t &in)
Definition: array.h:107
Definition: array.h:42
const T & front() const
Definition: array.h:159
Definition: TypeID.h:25
iterator_wrapper< typename base_t::reverse_iterator > reverse_iterator
Definition: array.h:116
const auto & operator*() const
Definition: array.h:86
auto operator-(int in)
Definition: array.h:106
auto & operator[](int offset)
Definition: array.h:111
array(const this_t &_in)
Definition: array.h:124
const T & back() const
Definition: array.h:157
void fill(const T &val)
Definition: array.h:161
iterator begin() noexcept
Definition: array.h:139
this_t & operator++()
Definition: array.h:100
bool valid
Definition: array.h:48
const T & operator[](size_t pos) const
Definition: array.h:151
ITERATOR_T wrapped_t
Definition: array.h:54
bool OK(bool begin_ok=true, bool end_ok=true) const
Definition: array.h:66
std::istream & operator>>(std::istream &is, emp::Ptr< T > &ptr)
Definition: Ptr.h:808
iterator end() noexcept
Definition: array.h:141
iterator insert(ARGS &&...args)
Definition: array.h:173
iterator erase(ARGS &&...args)
Definition: array.h:179
iterator_wrapper< typename base_t::const_reverse_iterator > const_reverse_iterator
Definition: array.h:117
this_t operator++(int x)
Definition: array.h:101
iterator_wrapper< typename base_t::const_iterator > const_iterator
Definition: array.h:115
A more dynamic replacement for standard library asserts.
array(const base_t &in)
Definition: array.h:126
void push_back(PB_Ts &&...args)
Definition: array.h:169
iterator_wrapper< ITERATOR_T > this_t
Definition: array.h:53
this_t & operator-=(int in)
Definition: array.h:110
auto operator->()
Definition: array.h:91
~iterator_wrapper()
Definition: array.h:63
const auto operator->() const
Definition: array.h:95
Setup an iterator wrapper to make sure that they&#39;re valid.
Definition: array.h:52
T & back()
Definition: array.h:156
void resize(size_t new_size)
Definition: array.h:165
iterator_wrapper< typename base_t::iterator > iterator
Definition: array.h:114
this_t & operator+=(int in)
Definition: array.h:109
typename base_t::reference reference
Definition: array.h:120
iterator_wrapper(const ITERATOR_T &_in, const vec_t *_v)
Definition: array.h:60
typename base_t::size_type size_type
Definition: array.h:119
const_iterator end() const noexcept
Definition: array.h:142
static std::string GetName()
Definition: TypeID.h:28
auto operator+(int in)
Definition: array.h:105
T & operator[](size_t pos)
Definition: array.h:146
constexpr size_t size() const
Definition: array.h:137
void insert(std::set< T > &s1, const std::set< T > &s2)
Insert the full contents of s2 into s1.
Definition: set_utils.h:24
void resize(size_t new_size, const T &val)
Definition: array.h:166
typename base_t::const_reference const_reference
Definition: array.h:121
If we are in emscripten, make sure to include the header.
Definition: array.h:37
this_t & operator=(const this_t &)=default
Build a debug wrapper emp::vector around std::vector.
Definition: vector.h:42
#define emp_assert(...)
Definition: assert.h:199
iterator emplace(ARGS &&...args)
Definition: array.h:185
array()
Definition: array.h:123
array(std::initializer_list< T > in_list)
Definition: array.h:125
~array()
Definition: array.h:129
T & front()
Definition: array.h:158
void pop_back()
Definition: array.h:170
const_iterator begin() const noexcept
Definition: array.h:140
this_t & operator--()
Definition: array.h:102
auto & operator*()
Definition: array.h:82
array(InputIt first, InputIt last)
Definition: array.h:128
const vec_t * v_ptr
What vector was this iterator created from?
Definition: array.h:58
void emplace_back(ARGS &&...args)
Definition: array.h:191
static std::string GetName()
Definition: array.h:217