SigUtil  0.95
Utility modules for modern C++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
array.hpp
Go to the documentation of this file.
1 /*
2 Copyright© 2014 Akihiro Nishimura
3 
4 This software is released under the MIT License.
5 http://opensource.org/licenses/mit-license.php
6 */
7 
8 #ifndef SIG_UTIL_ARRAY_HPP
9 #define SIG_UTIL_ARRAY_HPP
10 
11 #include "sigutil.hpp"
12 #include <array>
13 #include <initializer_list>
14 
15 namespace sig
16 {
18 
26 template <class T, size_t N>
27 class array
28 {
29 public:
30  using value_type = T;
31  using reference = T&;
32  using const_reference = T const&;
33  using pointer = T*;
34  using const_pointer = T const*;
35  using iterator = typename std::array<T, N>::iterator;
36  using const_iterator = typename std::array<T, N>::const_iterator;
37  using reverse_iterator = typename std::array<T, N>::reverse_iterator;
38  using const_reverse_iterator = typename std::array<T, N>::const_reverse_iterator;
39  using size_type = size_t;
40  using difference_type = typename std::array<T, N>::difference_type;
41 #if SIG_ENABLE_BOOST
42  using result_type = typename boost::call_traits<T>::value_type;
43  using param_type = typename boost::call_traits<T>::param_type;
44 #else
45  using result_type = value_type;
46  using param_type = typename std::conditional<std::is_class<T>::value, T const&, T>::type;
47 #endif
48 
49 private:
50  std::array<T, N> array_;
51  size_type tail_; // 現在使用している添字末尾
52 
53 private:
54  template <class OP, class C1, class C2>
55  void compound_assignment_(OP const& assign_op, C1& dest, C2 const& src)
56  {
57  auto it1 = std::begin(dest), end1 = std::end(dest);
58  auto it2 = std::begin(src), end2 = std::end(src);
59 
60  while (it1 != end1 && it2 != end2){
61  assign_op(*it1, *it2);
62  ++it1;
63  ++it2;
64  }
65  }
66 
67  void range_check_(size_type index)
68  {
69  if (index >= tail_){
70  throw std::out_of_range("invalid sig::array<T, N> subscript");
71  }
72  }
73 
74  // pos以降の要素を1つ後へずらす
75  iterator back_shift_(const_iterator pos)
76  {
77  auto it = rbegin();
78  for (auto pit = it; it.base() != pos; pit = it++){
79  *pit = std::move(*it);
80  }
81  return it.base();
82  }
83 
84  // pos以降の要素を1つ前へずらす
85  iterator front_shift_(iterator pos)
86  {
87  iterator post = pos;
88  for (auto pit = pos, end = this->end(); pos != end; pit = pos++){
89  *pit = std::move(*pos);
90  }
91  return post;
92  }
93 
94 public:
96  array() : tail_(0) {}
97 
99 
105  array(size_type size, T val) : tail_(0){ for(size_type i=0; i<size; ++i) push_back(val); }
106 
108 
113  array(std::initializer_list<T> init) : tail_(0)
114  {
115  assert(init.size() <= N);
116  for(auto it = init.begin(), end = init.end(); it != end; ++it){
117  array_[tail_] = std::move(*it);
118  ++tail_;
119  }
120  }
121 
123 
126  template <size_type M>
127  explicit array(std::array<T,M> const& src) : tail_(0)
128  {
129  static_assert(M <= N, "M must be less than N");
130  compound_assignment_([this](T& dest, ParamType<T> src){ dest = src; ++tail_; }, array_, src);
131  }
132 
134 
137  template <size_type M>
138  explicit array(sig::array<T,M> const& src) : tail_(src.size())
139  {
140  static_assert(M <= N, "M must be less than N");
141  compound_assignment_([this](T& dest, ParamType<T> src){ dest = src; }, array_, src.std_array());
142  }
143 
145 
148  array(array const& src) : tail_(src.tail_)
149  {
150  compound_assignment_([this](T& dest, ParamType<T> src){ dest = src; }, array_, src.array_);
151  }
152 
154 
159  array(array&& src) : tail_(0)
160  {
161  for (auto it = src.begin(), end = src.end(); it != end; ++it){
162  array_[tail_] = std::move(*it);
163  ++tail_;
164  }
165  src.tail_ = 0;
166  }
167 
169 
174  array& operator=(array const& src)
175  {
176  auto tmp = array(src);
177  swap(tmp);
178  return *this;
179  }
180 
182 
190  {
191  swap(src);
192  src.tail_ = 0;
193  return *this;
194  }
195 
197 
202  template <size_type M>
203  array& operator=(std::array<T,M> const& src)
204  {
205  static_assert(M <= N, "M must be less than N");
206  array copy(src);
207  swap(copy);
208  return *this;
209  }
210 
212 
217  template <size_type M>
219  {
220  static_assert(M <= N, "M must be less than N");
221  array copy(src);
222  swap(copy);
223  return *this;
224  }
225 
227  bool operator==(array const& obj){
228  if (tail_ != obj.tail_) return false;
229  bool same = true;
230  for (size_type i = 0; i < tail_; ++i) same = same && (array_[i] == obj.array_[i]);
231  return same;
232  }
233 
235  bool operator!=(array const& obj){
236  return !(*this == obj);
237  }
238 
240 
243  iterator begin() noexcept{ return array_.begin(); }
244  const_iterator begin() const noexcept{ return array_.begin(); }
245  const_iterator cbegin() const noexcept{ return array_.cbegin(); }
246 
248 
254  iterator end() noexcept{ return array_.begin() + tail_; }
255  const_iterator end() const noexcept{ return array_.begin() + tail_; }
256  const_iterator cend() const noexcept{ return array_.cbegin() + tail_; }
257 
259 
262  reverse_iterator rbegin() noexcept{ return array_.rend() - tail_; }
263  const_reverse_iterator rbegin() const noexcept{ return array_.rend() - tail_; }
264  const_reverse_iterator crbegin() const noexcept{ return array_.crend() - tail_; }
265 
267 
272  reverse_iterator rend() noexcept{ return array_.rend(); }
273  const_reverse_iterator rend() const noexcept{ return array_.rend(); }
274  const_reverse_iterator crend() const noexcept{ return array_.crend(); }
275 
277 
284  reference at(size_type pos){ range_check_(pos); return array_.at(pos); }
285  const_reference at(size_type pos) const{ range_check_(pos); return array_.at(pos); }
286 
288 
295  reference operator [](size_type pos){ return array_[pos]; }
296  const_reference operator [](size_type pos) const{ return array_[pos]; }
297 
299 
302  reference front(){ return array_.front(); }
303  const_reference front() const{ return array_.front(); }
304 
306 
309  reference back(){ return tail_ ? array_[tail_-1] : array_.front(); }
310  const_reference back() const{ return tail_ ? array_[tail_ - 1] : array_.front(); }
311 
313 
316  bool empty() const noexcept{ return tail_ == 0; }
317 
319 
325  size_type size() const noexcept{ return tail_; }
326 
328 
331  size_type max_size() const noexcept{ return N; }
332 
334 
337  value_type* data() noexcept{ return array_.data(); }
338  value_type const* data() const noexcept{ return array_.data(); }
339 
341 
344  auto std_array() noexcept ->std::array<T, N>&{ return array_; }
345  auto std_array() const noexcept ->std::array<T, N> const&{ return array_; }
346 
348 
351  void fill(value_type const& val){ array_.fill(val); tail_ = N; }
352 
354 
357  void swap(array& other) //noexcept(noexcept(swap(std::declval<value_type&>(), std::declval<value_type&>())))
358  {
359  std::swap(array_, other.array_);
360  std::swap(tail_, other.tail_);
361  }
362 
364 
371  void push_back(value_type const& val)
372  {
373  if (tail_ >= N) throw std::length_error("this container reached upper maxsize limit. so, can't hold more elements.");
374  array_[tail_++] = val;
375  }
376  void push_back(value_type&& val)
377  {
378  if (tail_ >= N) throw std::length_error("this container reached upper maxsize limit. so, can't hold more elements.");
379  array_[tail_++] = std::forward<value_type>(val);
380  }
381 
383  void pop_back() noexcept{ if(tail_ > 0) --tail_; }
384 
386 
396  iterator insert(const_iterator position, const value_type& val)
397  {
398  if (tail_ >= N) throw std::length_error("this container reached upper maxsize limit. so, can't hold more elements.");
399  ++tail_;
400  auto p = back_shift_(position);
401  *p = val;
402  return p;
403  }
405  {
406  if (tail_ >= N) throw std::length_error("this container reached upper maxsize limit. so, can't hold more elements.");
407  ++tail_;
408  auto p = back_shift_(position);
409  *p = std::move(val);
410  return p;
411  }
412 
414 
422  {
423  auto p = front_shift_(position);
424  --tail_;
425  return p;
426  }
427 
429  void clear() noexcept{ tail_ = 0; }
430 };
431 
432 }
433 #endif
void push_back(value_type &&val)
Definition: array.hpp:376
size_type max_size() const noexcept
コンテナの最大容量を返す
Definition: array.hpp:331
array(std::initializer_list< T > init)
initializer_list から値をムーブしてコンストラクト
Definition: array.hpp:113
const_reference front() const
Definition: array.hpp:303
size_type size() const noexcept
コンテナに格納された要素数を返す
Definition: array.hpp:325
array & operator=(array const &src)
コピー代入演算子
Definition: array.hpp:174
T const * const_pointer
Definition: array.hpp:34
size_t size_type
Definition: array.hpp:39
reference front()
先頭要素へのアクセス
Definition: array.hpp:302
auto std_array() const noexcept-> std::array< T, N > const &
Definition: array.hpp:345
T value_type
Definition: array.hpp:30
void fill(value_type const &val)
コンテナの全要素(最大容量まで)を指定した値でコピーする
Definition: array.hpp:351
void pop_back() noexcept
コンテナの末尾から要素を取り除く
Definition: array.hpp:383
array(size_type size, T val)
値をコピーしてコンストラクト
Definition: array.hpp:105
typename std::array< T, N >::iterator iterator
Definition: array.hpp:35
auto end(C &&c) -> std::move_iterator< typename RC::iterator >
typename std::array< T, N >::difference_type difference_type
Definition: array.hpp:40
typename std::array< T, N >::const_iterator const_iterator
Definition: array.hpp:36
const_iterator cend() const noexcept
Definition: array.hpp:256
array(std::array< T, M > const &src)
std::array から値をコピーしてコンストラクト
Definition: array.hpp:127
const_reverse_iterator rend() const noexcept
Definition: array.hpp:273
typename std::array< T, N >::reverse_iterator reverse_iterator
Definition: array.hpp:37
array & operator=(array &&src)
ムーブ代入演算子
Definition: array.hpp:189
array(array const &src)
コピーコンストラクタ
Definition: array.hpp:148
void push_back(value_type const &val)
コンテナの末尾に指定した値を追加する
Definition: array.hpp:371
T & reference
Definition: array.hpp:31
const_iterator end() const noexcept
Definition: array.hpp:255
T const & const_reference
Definition: array.hpp:32
typename std::array< T, N >::const_reverse_iterator const_reverse_iterator
Definition: array.hpp:38
typename boost::call_traits< T >::value_type result_type
Definition: array.hpp:42
reference at(size_type pos)
添字による要素へのアクセス
Definition: array.hpp:284
STLライクな静的配列
Definition: array.hpp:27
const_reverse_iterator rbegin() const noexcept
Definition: array.hpp:263
array & operator=(sig::array< T, M > const &src)
sig::array(サイズが異なる)から値をコピーして代入
Definition: array.hpp:218
array()
デフォルトコンストラクタ
Definition: array.hpp:96
array(sig::array< T, M > const &src)
sig::array(サイズが異なる)から値をコピーしてコンストラクト
Definition: array.hpp:138
const_reverse_iterator crend() const noexcept
Definition: array.hpp:274
reference operator[](size_type pos)
添字による要素へのアクセス
Definition: array.hpp:295
iterator insert(const_iterator position, value_type &&val)
Definition: array.hpp:404
void clear() noexcept
コンテナを空にする
Definition: array.hpp:429
auto std_array() noexcept-> std::array< T, N > &
内部で保有するstd::arrayへの参照を返す
Definition: array.hpp:344
T * pointer
Definition: array.hpp:33
iterator end() noexcept
末尾要素の後ろを指すイテレータを返す
Definition: array.hpp:254
const_iterator begin() const noexcept
Definition: array.hpp:244
typename boost::call_traits< T >::param_type param_type
Definition: array.hpp:43
iterator insert(const_iterator position, const value_type &val)
指定位置の後ろに指定した値を挿入する
Definition: array.hpp:396
const_reverse_iterator crbegin() const noexcept
Definition: array.hpp:264
const_iterator cbegin() const noexcept
Definition: array.hpp:245
void swap(array &other)
他の最大容量が同じsig::arrayと保持メンバを入れ替える
Definition: array.hpp:357
iterator begin() noexcept
先頭要素を指すイテレータを返す
Definition: array.hpp:243
value_type * data() noexcept
内部で保有する生配列へのポインタを返す
Definition: array.hpp:337
reference back()
末尾要素へのアクセス
Definition: array.hpp:309
array & operator=(std::array< T, M > const &src)
std::array から値をコピーして代入
Definition: array.hpp:203
bool empty() const noexcept
コンテナが空であるかを確認
Definition: array.hpp:316
reverse_iterator rend() noexcept
先頭要素の前を指す逆イテレータを返す
Definition: array.hpp:272
iterator erase(iterator position)
指定位置の要素を取り除く
Definition: array.hpp:421
const_reference back() const
Definition: array.hpp:310
Definition: array.hpp:15
bool operator!=(array const &obj)
非等値比較演算子
Definition: array.hpp:235
value_type const * data() const noexcept
Definition: array.hpp:338
const_reference at(size_type pos) const
Definition: array.hpp:285
reverse_iterator rbegin() noexcept
末尾要素を指す逆イテレータを返す
Definition: array.hpp:262
bool operator==(array const &obj)
等値比較演算子
Definition: array.hpp:227
auto copy(C &&src) -> RC
別の種類のコンテナに要素をコピーする
array(array &&src)
ムーブコンストラクタ
Definition: array.hpp:159
auto begin(C &&c) -> std::move_iterator< typename RC::iterator >