y3c-stl 0.3.3
Friendly C++ STL wrapper with automatic stacktrace
Loading...
Searching...
No Matches
vector.h
Go to the documentation of this file.
1#pragma once
2#include "y3c/terminate.h"
3#include "y3c/wrap.h"
4#include "y3c/typename.h"
5#include "y3c/iterator.h"
6#include <vector>
7#include <memory>
8
9namespace y3c {
10
22template <typename T>
23class vector {
24 std::vector<T> base_;
25 std::unique_ptr<internal::life> elems_life_;
26 internal::life life_;
27
31 void init_elems_life() {
32 if (!base_.empty()) {
33 elems_life_ = std::unique_ptr<internal::life>(
34 new internal::life(&base_[0], &base_[0] + base_.size()));
35 } else {
36 elems_life_ = std::unique_ptr<internal::life>(
37 new internal::life(nullptr, nullptr));
38 }
39 }
45 void update_elems_life(const void *invalidate_from = nullptr) {
46 if (!base_.empty()) {
47 elems_life_->update(&base_[0], &base_[0] + base_.size(),
48 invalidate_from);
49 } else {
50 elems_life_->update(nullptr, nullptr);
51 }
52 }
53
54 const std::string &type_name() const {
55 return internal::get_type_name<vector>();
56 }
57 const std::string &iter_name() const {
58 static std::string name =
59 internal::get_type_name<vector>() + "::iterator";
60 return name;
61 }
62
63 std::size_t assert_iter(const internal::contiguous_iterator<const T> &pos,
64 const std::string &func,
65 internal::skip_trace_tag = {}) const {
66 if (*elems_life_ != pos.get_observer_()) {
68 }
69 pos.get_observer_().assert_iter(pos, func);
70 if (base_.size() == 0) {
71 return 0;
72 } else {
73 return y3c::internal::unwrap(pos) - &base_[0];
74 }
75 }
76 std::size_t
77 assert_iter_including_end(const internal::contiguous_iterator<const T> &pos,
78 const std::string &func,
79 internal::skip_trace_tag = {}) const {
80 if (*elems_life_ != pos.get_observer_()) {
82 }
84 if (base_.size() == 0) {
85 return 0;
86 } else {
87 return y3c::internal::unwrap(pos) - &base_[0];
88 }
89 }
90
91 public:
95 vector() : base_(), life_(this) { init_elems_life(); }
99 vector(const vector &other) : base_(other.base_), life_(this) {
100 init_elems_life();
101 }
109 vector(vector &&other)
110 : base_(std::move(other.base_)),
111 elems_life_(std::move(other.elems_life_)), life_(this) {}
118 vector &operator=(const vector &other) {
119 this->base_ = other.base_;
120 init_elems_life();
121 return *this;
122 }
131 if (this != std::addressof(other)) {
132 this->base_ = std::move(other.base_);
133 this->elems_life_ = std::move(other.elems_life_);
134 }
135 return *this;
136 }
137 ~vector() = default;
138
139 using value_type = T;
140 using size_type = std::size_t;
141 using difference_type = std::ptrdiff_t;
148
152 vector(const std::vector<T> &other) : base_(other), life_(this) {
153 init_elems_life();
154 }
158 vector(const std::vector<T> &&other)
159 : base_(std::move(other)), life_(this) {
160 init_elems_life();
161 }
168 vector &operator=(const std::vector<T> &other) {
169 this->base_ = other;
170 init_elems_life();
171 return *this;
172 }
179 vector &operator=(std::vector<T> &&other) {
180 this->base_ = std::move(other);
181 init_elems_life();
182 return *this;
183 }
184
188 explicit vector(size_type count) : base_(count), life_(this) {
189 init_elems_life();
190 }
194 vector(size_type count, const T &value) : base_(count, value), life_(this) {
195 init_elems_life();
196 }
200 template <typename InputIt>
201 vector(InputIt first, InputIt last) : base_(first, last), life_(this) {
202 init_elems_life();
203 }
207 vector(std::initializer_list<T> init) : base_(init), life_(this) {
208 init_elems_life();
209 }
215 vector &operator=(std::initializer_list<T> ilist) {
216 base_ = ilist;
217 init_elems_life();
218 return *this;
219 }
220
227 void assign(size_type count, const T &value) {
228 base_.assign(count, value);
229 init_elems_life();
230 }
237 template <typename InputIt>
238 void assign(InputIt first, InputIt last) {
239 base_.assign(first, last);
240 init_elems_life();
241 }
248 void assign(std::initializer_list<T> ilist) {
249 base_.assign(ilist);
250 init_elems_life();
251 }
258 void clear() {
259 base_.clear();
260 init_elems_life();
261 }
262
269 void reserve(size_type new_cap) {
270 base_.reserve(new_cap);
271 update_elems_life();
272 }
280 base_.shrink_to_fit();
281 update_elems_life();
282 }
283
294 static std::string func = type_name() + "::erase()";
295 std::size_t index = assert_iter(pos, func);
296 base_.erase(base_.begin() + index);
297 update_elems_life(&base_[0] + index);
298 return iterator(&base_[0] + index, elems_life_->observer(),
299 &iter_name());
300 }
312 static std::string func = type_name() + "::erase()";
313 if (*elems_life_ != begin.get_observer_() ||
314 *elems_life_ != end.get_observer_()) {
316 }
318 std::size_t index_begin = y3c::internal::unwrap(begin) - &base_[0];
319 std::size_t index_end = y3c::internal::unwrap(end) - &base_[0];
320 base_.erase(base_.begin() + index_begin, base_.begin() + index_end);
321 update_elems_life(&base_[0] + index_begin);
322 return iterator(&base_[0] + index_begin, elems_life_->observer(),
323 &iter_name());
324 }
333 void push_back(const T &value) {
334 base_.push_back(value);
335 update_elems_life();
336 }
345 void push_back(T &&value) {
346 base_.push_back(std::move(value));
347 update_elems_life();
348 }
357 template <typename... Args>
358 reference emplace_back(Args &&...args) {
359 base_.emplace_back(std::forward<Args>(args)...);
360 update_elems_life();
361 return back();
362 }
363
375 iterator insert(const_iterator pos, const T &value,
377 static std::string func = type_name() + "::insert()";
378 std::size_t index = assert_iter_including_end(pos, func);
379 base_.insert(base_.begin() + index, value);
380 update_elems_life(&base_[0] + index);
381 return iterator(&base_[0] + index, elems_life_->observer(),
382 &iter_name());
383 }
397 static std::string func = type_name() + "::insert()";
398 std::size_t index = assert_iter_including_end(pos, func);
399 base_.insert(base_.begin() + index, std::move(value));
400 update_elems_life(&base_[0] + index);
401 return iterator(&base_[0] + index, elems_life_->observer(),
402 &iter_name());
403 }
416 iterator insert(const_iterator pos, size_type count, const T &value,
418 static std::string func = type_name() + "::insert()";
419 std::size_t index = assert_iter_including_end(pos, func);
420 base_.insert(base_.begin() + index, count, std::move(value));
421 update_elems_life(&base_[0] + index);
422 return iterator(&base_[0] + index, elems_life_->observer(),
423 &iter_name());
424 }
436 template <typename InputIt,
437 typename std::enable_if<
438 std::is_convertible<
439 typename std::iterator_traits<InputIt>::reference,
440 value_type>::value,
441 std::nullptr_t>::type = nullptr>
442 iterator insert(const_iterator pos, InputIt first, InputIt last,
444 static std::string func = type_name() + "::insert()";
445 std::size_t index = assert_iter_including_end(pos, func);
446 base_.insert(base_.begin() + index, first, last);
447 update_elems_life(&base_[0] + index);
448 return iterator(&base_[0] + index, elems_life_->observer(),
449 &iter_name());
450 }
462 iterator insert(const_iterator pos, std::initializer_list<T> ilist,
464 static std::string func = type_name() + "::insert()";
465 std::size_t index = assert_iter_including_end(pos, func);
466 base_.insert(base_.begin() + index, ilist);
467 update_elems_life(&base_[0] + index);
468 return iterator(&base_[0] + index, elems_life_->observer(),
469 &iter_name());
470 }
482 template <typename... Args, typename = internal::skip_trace_tag>
483 iterator emplace(const_iterator pos, Args &&...args) {
484 static std::string func = type_name() + "::emplace()";
485 std::size_t index = assert_iter_including_end(pos, func);
486 base_.emplace(base_.begin() + index, std::forward<Args>(args)...);
487 update_elems_life(&base_[0] + index);
488 return iterator(&base_[0] + index, elems_life_->observer(),
489 &iter_name());
490 }
491
499 void resize(size_type count) {
500 base_.resize(count);
501 update_elems_life();
502 }
511 void resize(size_type count, const T &value) {
512 base_.resize(count, value);
513 update_elems_life();
514 }
515
523 if (base_.empty()) {
524 static std::string func = type_name() + "::pop_back()";
526 }
527 base_.pop_back();
528 update_elems_life();
529 }
530
538 if (n >= base_.size()) {
539 static std::string func = type_name() + "::at()";
540 throw y3c::out_of_range(func, base_.size(),
541 static_cast<std::ptrdiff_t>(n));
542 }
543 return reference(&this->base_[n], elems_life_->observer());
544 }
552 if (n >= base_.size()) {
553 static std::string func = type_name() + "::at()";
554 throw y3c::out_of_range(func, base_.size(),
555 static_cast<std::ptrdiff_t>(n));
556 }
557 return const_reference(&this->base_[n], elems_life_->observer());
558 }
565 template <typename = internal::skip_trace_tag>
567 if (n >= base_.size()) {
568 static std::string func = type_name() + "::operator[]()";
570 func, base_.size(), static_cast<std::ptrdiff_t>(n));
571 }
572 return reference(&this->base_[n], elems_life_->observer());
573 }
580 template <typename = internal::skip_trace_tag>
582 if (n >= base_.size()) {
583 static std::string func = type_name() + "::operator[]()";
585 func, base_.size(), static_cast<std::ptrdiff_t>(n));
586 }
587 return const_reference(&this->base_[n], elems_life_->observer());
588 }
596 if (base_.empty()) {
597 static std::string func = type_name() + "::front()";
599 }
600 return reference(&base_.front(), elems_life_->observer());
601 }
609 if (base_.empty()) {
610 static std::string func = type_name() + "::front()";
612 }
613 return const_reference(&base_.front(), elems_life_->observer());
614 }
622 if (base_.empty()) {
623 static std::string func = type_name() + "::back()";
625 }
626 return reference(&base_.back(), elems_life_->observer());
627 }
635 if (base_.empty()) {
636 static std::string func = type_name() + "::back()";
638 }
639 return const_reference(&base_.back(), elems_life_->observer());
640 }
641
649 if (base_.empty()) {
650 return pointer(nullptr, elems_life_->observer());
651 }
652 return pointer(&this->base_[0], elems_life_->observer());
653 }
661 if (base_.empty()) {
662 return const_pointer(nullptr, elems_life_->observer());
663 }
664 return const_pointer(&this->base_[0], elems_life_->observer());
665 }
666
674 if (base_.empty()) {
675 return iterator(nullptr, elems_life_->observer(), &iter_name());
676 }
677 return iterator(&this->base_.front(), elems_life_->observer(),
678 &iter_name());
679 }
687 if (base_.empty()) {
688 return const_iterator(nullptr, elems_life_->observer(),
689 &iter_name());
690 }
691 return const_iterator(&this->base_.front(), elems_life_->observer(),
692 &iter_name());
693 }
700 const_iterator cbegin() const { return begin(); }
707 iterator end() { return begin() + base_.size(); }
714 const_iterator end() const { return begin() + base_.size(); }
721 const_iterator cend() const { return begin() + base_.size(); }
722
726 bool empty() const { return base_.empty(); }
730 size_type size() const { return base_.size(); }
734 size_type max_size() const { return base_.max_size(); }
738 size_type capacity() const { return base_.capacity(); }
739
746 void swap(vector &other) {
747 base_.swap(other.base_);
748 elems_life_.swap(other.elems_life_);
749 update_elems_life(&base_[0] + base_.size());
750 other.update_elems_life(&other.base_[0] + other.base_.size());
751 }
752
756 operator const std::vector<T> &() const noexcept { return base_; }
757
758 operator wrap<const vector &>() const noexcept {
759 return wrap<const vector &>(this, life_.observer());
760 }
762 return wrap<const vector *>(this, life_.observer());
763 }
764};
765
766template <typename T>
767const std::vector<T> &unwrap(const vector<T> &wrapper) noexcept {
768 return static_cast<const std::vector<T> &>(wrapper);
769}
770
771template <typename T>
772void swap(vector<T> &lhs, vector<T> &rhs) {
773 lhs.swap(rhs);
774}
775
776template <typename T>
777bool operator==(const vector<T> &lhs, const vector<T> &rhs) {
778 return unwrap(lhs) == unwrap(rhs);
779}
780template <typename T>
781bool operator!=(const vector<T> &lhs, const vector<T> &rhs) {
782 return unwrap(lhs) != unwrap(rhs);
783}
784template <typename T>
785bool operator<(const vector<T> &lhs, const vector<T> &rhs) {
786 return unwrap(lhs) < unwrap(rhs);
787}
788template <typename T>
789bool operator<=(const vector<T> &lhs, const vector<T> &rhs) {
790 return unwrap(lhs) <= unwrap(rhs);
791}
792template <typename T>
793bool operator>(const vector<T> &lhs, const vector<T> &rhs) {
794 return unwrap(lhs) > unwrap(rhs);
795}
796template <typename T>
797bool operator>=(const vector<T> &lhs, const vector<T> &rhs) {
798 return unwrap(lhs) >= unwrap(rhs);
799}
800
801} // namespace y3c
array, vector など各種コンテナのイテレータ
Definition iterator.h:26
const life_observer & get_observer_() const
Definition iterator.h:108
void assert_range_iter(const contiguous_iterator< element_type > &begin, const contiguous_iterator< element_type > &end, const std::string &func, internal::skip_trace_tag={}) const
Definition life.h:173
element_type * assert_iter_including_end(const contiguous_iterator< element_type > &iter, const std::string &func, internal::skip_trace_tag={}) const
Definition life.h:152
element_type * assert_iter(const contiguous_iterator< element_type > &iter, const std::string &func, internal::skip_trace_tag={}) const
Definition life.h:130
オブジェクトのライフタイムを管理するクラス
Definition life.h:207
life_observer observer() const
Definition life.h:233
Definition terminate.h:179
可変長配列 (std::vector)
Definition vector.h:23
vector(std::initializer_list< T > init)
std::initializer_listで初期化
Definition vector.h:207
iterator insert(const_iterator pos, InputIt first, InputIt last, internal::skip_trace_tag={})
要素の挿入
Definition vector.h:442
const_reference at(size_type n, internal::skip_trace_tag={}) const
要素アクセス(const)
Definition vector.h:551
vector & operator=(std::vector< T > &&other)
std::vectorからのムーブ代入
Definition vector.h:179
void resize(size_type count)
サイズを変更
Definition vector.h:499
const_iterator begin() const
先頭要素を指すconstイテレータを取得
Definition vector.h:686
void assign(std::initializer_list< T > ilist)
initializer_listで要素を置き換える
Definition vector.h:248
reference front(internal::skip_trace_tag={})
先頭の要素へのアクセス
Definition vector.h:595
const_pointer data() const
先頭要素へのconstポインタを取得
Definition vector.h:660
pointer data()
先頭要素へのポインタを取得
Definition vector.h:648
reference operator[](size_type n)
要素アクセス
Definition vector.h:566
const_iterator cbegin() const
先頭要素を指すconstイテレータを取得
Definition vector.h:700
reference at(size_type n, internal::skip_trace_tag={})
要素アクセス
Definition vector.h:537
void swap(vector &other)
別のvectorと要素を入れ替える
Definition vector.h:746
iterator erase(const_iterator pos, internal::skip_trace_tag={})
要素の削除
Definition vector.h:293
iterator insert(const_iterator pos, size_type count, const T &value, internal::skip_trace_tag={})
要素の挿入
Definition vector.h:416
iterator insert(const_iterator pos, const T &value, internal::skip_trace_tag={})
要素の挿入
Definition vector.h:375
void shrink_to_fit()
容量の縮小
Definition vector.h:279
size_type size() const
配列のサイズを取得
Definition vector.h:730
vector & operator=(vector &&other)
すべての要素をムーブ
Definition vector.h:130
bool empty() const
sizeが0かどうかを返す
Definition vector.h:726
void push_back(const T &value)
要素の追加
Definition vector.h:333
internal::contiguous_iterator< T > iterator
Definition vector.h:146
wrap< const vector * > operator&() const
Definition vector.h:761
vector(const vector &other)
新しい領域にコピー構築
Definition vector.h:99
iterator emplace(const_iterator pos, Args &&...args)
要素の挿入
Definition vector.h:483
void reserve(size_type new_cap)
領域の確保
Definition vector.h:269
vector(const std::vector< T > &other)
std::vectorからコピー構築
Definition vector.h:152
vector(vector &&other)
ムーブ構築
Definition vector.h:109
const_iterator cend() const
末尾要素を指すconstイテレータを取得
Definition vector.h:721
size_type max_size() const
配列の最大サイズを取得
Definition vector.h:734
wrap_ref< T > reference
Definition vector.h:142
vector & operator=(std::initializer_list< T > ilist)
initialization_listの代入
Definition vector.h:215
void push_back(T &&value)
要素の追加
Definition vector.h:345
void assign(size_type count, const T &value)
サイズと値を指定して要素を置き換える
Definition vector.h:227
vector(size_type count)
サイズ指定して初期化
Definition vector.h:188
vector(InputIt first, InputIt last)
イテレータで初期化
Definition vector.h:201
void assign(InputIt first, InputIt last)
イテレータからのコピーで要素を置き換える
Definition vector.h:238
reference emplace_back(Args &&...args)
要素の追加
Definition vector.h:358
reference back(internal::skip_trace_tag={})
末尾の要素へのアクセス
Definition vector.h:621
vector & operator=(const vector &other)
すべての要素をコピー
Definition vector.h:118
ptr< T > pointer
Definition vector.h:144
~vector()=default
iterator insert(const_iterator pos, T &&value, internal::skip_trace_tag={})
要素の挿入
Definition vector.h:395
const_reference back(internal::skip_trace_tag={}) const
末尾の要素へのアクセス(const)
Definition vector.h:634
const_ptr< T > const_pointer
Definition vector.h:145
vector & operator=(const std::vector< T > &other)
std::vectorからのコピー代入
Definition vector.h:168
internal::contiguous_iterator< const T > const_iterator
Definition vector.h:147
vector(const std::vector< T > &&other)
std::vectorからムーブ構築
Definition vector.h:158
void clear()
要素のクリア
Definition vector.h:258
iterator end()
末尾要素を指すイテレータを取得
Definition vector.h:707
iterator erase(const_iterator begin, const_iterator end, internal::skip_trace_tag={})
要素の削除
Definition vector.h:310
void pop_back(internal::skip_trace_tag={})
末尾の要素を削除
Definition vector.h:522
const_iterator end() const
末尾要素を指すconstイテレータを取得
Definition vector.h:714
std::ptrdiff_t difference_type
Definition vector.h:141
size_type capacity() const
現在のメモリ確保済みのサイズを取得
Definition vector.h:738
iterator begin()
先頭要素を指すイテレータを取得
Definition vector.h:673
const_wrap_ref< T > const_reference
Definition vector.h:143
vector(size_type count, const T &value)
サイズと値を指定して初期化
Definition vector.h:194
vector()
サイズ0のvectorを作成する
Definition vector.h:95
iterator insert(const_iterator pos, std::initializer_list< T > ilist, internal::skip_trace_tag={})
要素の挿入
Definition vector.h:462
const_reference front(internal::skip_trace_tag={}) const
先頭の要素へのアクセス(const)
Definition vector.h:608
const_reference operator[](size_type n) const
要素アクセス(const)
Definition vector.h:581
std::size_t size_type
Definition vector.h:140
T value_type
Definition vector.h:139
void resize(size_type count, const T &value)
サイズを変更
Definition vector.h:511
ポインタ型wrap: element_type型のデータへのポインタと、 このポインタ自体の生存状態を管理するクラス
Definition wrap.h:318
参照型wrap: element_type型のデータへの参照を持つクラス
Definition wrap.h:168
値型wrap: base_type型のデータと、このデータの生存状態を管理するクラス
Definition wrap.h:26
void terminate_ub_wrong_iter(std::string func, Args &&...args)
Definition terminate.h:135
element_type * unwrap(const contiguous_iterator< element_type > &wrapper) noexcept
Definition iterator.h:209
void terminate_ub_out_of_range(std::string func, Args &&...args)
Definition terminate.h:132
Definition array.h:8
bool operator!=(const array< T, N > &lhs, const array< T, N > &rhs)
Definition array.h:390
bool operator<=(const array< T, N > &lhs, const array< T, N > &rhs)
Definition array.h:398
void swap(array< T, N > &lhs, array< T, N > &rhs)
Definition array.h:381
bool operator==(const array< T, N > &lhs, const array< T, N > &rhs)
Definition array.h:386
std::array< T, N > & unwrap(array< T, N > &wrapper) noexcept
Definition array.h:372
bool operator>(const array< T, N > &lhs, const array< T, N > &rhs)
Definition array.h:402
bool operator<(const array< T, N > &lhs, const array< T, N > &rhs)
Definition array.h:394
bool operator>=(const array< T, N > &lhs, const array< T, N > &rhs)
Definition array.h:406
Definition terminate.h:27