y3c-stl 0.3.3
Friendly C++ STL wrapper with automatic stacktrace
Loading...
Searching...
No Matches
wrap.h
Go to the documentation of this file.
1#pragma once
2#include "y3c/terminate.h"
3#include "y3c/life.h"
4#include "y3c/typename.h"
5#include <memory>
6
7namespace y3c {
8template <typename base_type>
9class wrap;
10template <typename element_type>
11element_type &unwrap(const wrap<element_type &> &wrapper,
12 internal::skip_trace_tag = {});
13
25template <typename base_type>
26class wrap {
27 static_assert(!std::is_void<base_type>::value,
28 "y3c::wrap cannot have void value");
29 static_assert(!std::is_const<base_type>::value,
30 "y3c::wrap cannot have const value");
31
32 const std::string &type_name() const {
33 return internal::get_type_name<wrap>();
34 }
35
36 protected:
37 base_type base_;
39
40 public:
44 wrap() : base_(), life_(&base_) {}
48 wrap(const wrap &other) : base_(other.base_), life_(&base_) {}
54 wrap(wrap &&other) : base_(std::move(other.base_)), life_(&base_) {}
58 wrap &operator=(const wrap &other) {
59 base_ = other.base_;
60 return *this;
61 }
67 wrap &operator=(wrap &&other) {
68 base_ = std::move(other.base_);
69 return *this;
70 }
71 ~wrap() = default;
72
76 template <typename... Args>
77 wrap(Args &&...args) : base_{std::forward<Args>(args)...}, life_(&base_) {}
81 template <typename V>
82 wrap &operator=(V &&args) {
83 base_ = std::forward<V>(args);
84 return *this;
85 }
86
87 template <typename>
88 friend class wrap;
89
93 operator base_type &() noexcept { return this->base_; }
97 operator const base_type &() const noexcept { return this->base_; }
98
105 template <typename T = base_type,
106 typename E = typename std::remove_extent<base_type>::type,
107 typename std::enable_if<std::is_array<T>::value,
108 std::nullptr_t>::type = nullptr,
109 typename = internal::skip_trace_tag>
110 wrap<E &> operator[](std::ptrdiff_t i) {
111 static std::string func = type_name() + "::operator[]()";
112 return wrap<E &>(life_.observer().assert_ptr(&base_[i], func),
113 life_.observer());
114 }
121 template <typename T = base_type,
122 typename E = typename std::remove_extent<base_type>::type,
123 typename std::enable_if<std::is_array<T>::value,
124 std::nullptr_t>::type = nullptr,
125 typename = internal::skip_trace_tag>
126 wrap<const E &> operator[](std::ptrdiff_t i) const {
127 static std::string func = type_name() + "::operator[]()";
128 return wrap<const E &>(life_.observer().assert_ptr(&base_[i], func),
129 life_.observer());
130 }
131
134 }
137 }
138};
139template <typename base_type,
140 typename std::enable_if<!std::is_pointer<base_type>::value &&
141 !std::is_reference<base_type>::value,
142 std::nullptr_t>::type = nullptr>
143base_type &unwrap(wrap<base_type> &wrapper) noexcept {
144 return static_cast<base_type &>(wrapper);
145}
146template <typename base_type,
147 typename std::enable_if<!std::is_pointer<base_type>::value &&
148 !std::is_reference<base_type>::value,
149 std::nullptr_t>::type = nullptr>
150const base_type &unwrap(const wrap<base_type> &wrapper) noexcept {
151 return static_cast<const base_type &>(wrapper);
152}
153
167template <typename element_type>
168class wrap<element_type &> {
169 static_assert(
170 !std::is_void<typename std::remove_const<element_type>::type>::value,
171 "y3c::wrap cannot have reference to void");
172
173 element_type *ptr_;
174 internal::life_observer observer_;
175
176 const std::string &type_name() const {
177 return internal::get_type_name<wrap>();
178 }
179
180 element_type *assert_ptr(const std::string &func,
181 internal::skip_trace_tag = {}) const {
182 return observer_.assert_ptr(ptr_, func);
183 }
184
185 public:
186 wrap(element_type *ptr, internal::life_observer observer) noexcept
187 : ptr_(ptr), observer_(observer) {}
188
192 template <typename T,
193 typename std::enable_if<!std::is_pointer<T>::value &&
194 !std::is_reference<T>::value,
195 std::nullptr_t>::type = nullptr>
196 wrap(wrap<T> &wrapper)
197 : ptr_(&wrapper.base_), observer_(wrapper.life_.observer()) {}
198
202 template <typename T, typename E = element_type,
203 typename std::enable_if<!std::is_pointer<T>::value &&
204 !std::is_reference<T>::value &&
205 std::is_const<E>::value,
206 std::nullptr_t>::type = nullptr>
207 wrap(const wrap<T> &wrapper)
208 : ptr_(&wrapper.base_), observer_(wrapper.life_.observer()) {}
209
213 template <typename T>
214 wrap(const wrap<T &> &ref) noexcept
215 : ptr_(ref.ptr_), observer_(ref.observer_) {}
216
220 template <typename V, typename = internal::skip_trace_tag>
221 wrap &operator=(V &&args) {
222 static std::string func = type_name() + "::operator=()";
223 *assert_ptr(func) = std::forward<V>(args);
224 return *this;
225 }
226
230 wrap(const wrap &) noexcept = default;
234 template <typename = internal::skip_trace_tag>
235 wrap &operator=(const wrap &other) {
236 static std::string func = type_name() + "::operator=()";
237 static std::string func2 =
238 "cast from " + other.type_name() + " to reference";
239 *assert_ptr(func) = *other.assert_ptr(func2);
240 return *this;
241 }
247 template <typename = internal::skip_trace_tag>
248 wrap &operator=(wrap &&other) {
249 if (this != std::addressof(other)) {
250 static std::string func = type_name() + "::operator=()";
251 static std::string func2 =
252 "cast from " + other.type_name() + " to reference";
253 *assert_ptr(func) = std::move(*other.assert_ptr(func2));
254 }
255 return *this;
256 }
257 ~wrap() = default;
258
259 template <typename T>
260 friend class wrap;
261 friend element_type &y3c::unwrap<element_type>(const wrap<element_type &> &,
263
269 template <typename = internal::skip_trace_tag>
270 operator element_type &() {
271 static std::string func2 = "cast from " + type_name() + " to reference";
272 return *assert_ptr(func2);
273 }
274
281 template <typename T = element_type,
282 typename E = typename std::remove_extent<element_type>::type,
283 typename std::enable_if<std::is_array<T>::value,
284 std::nullptr_t>::type = nullptr,
285 typename = internal::skip_trace_tag>
286 wrap<E &> operator[](std::ptrdiff_t i) {
287 static std::string func = type_name() + "::operator[]()";
288 return wrap<E &>(&assert_ptr(func)[0][i], observer_);
289 }
290
292 return wrap<element_type *>(ptr_, observer_);
293 }
294};
295
296template <typename element_type>
297element_type &unwrap(const wrap<element_type &> &wrapper,
299 static std::string func = "y3c::unwrap(" + wrapper.type_name() + ")";
300 return *wrapper.assert_ptr(func);
301}
302
317template <typename element_type>
318class wrap<element_type *> {
319 element_type *ptr_;
320 internal::life_observer observer_;
321 internal::life life_;
322
323 const std::string &type_name() const {
324 return internal::get_type_name<wrap>();
325 }
326
327 element_type *assert_ptr(const std::string &func,
328 internal::skip_trace_tag = {}) const {
329 return observer_.assert_ptr(ptr_, func);
330 }
331
332 public:
333 wrap(element_type *ptr, internal::life_observer observer) noexcept
334 : ptr_(ptr), observer_(observer), life_(&ptr_) {}
335
339 template <typename T, std::size_t N,
340 typename std::enable_if<!std::is_pointer<T>::value &&
341 !std::is_reference<T>::value,
342 std::nullptr_t>::type = nullptr>
344 : ptr_(&array.base_[0]), observer_(array.life_.observer()),
345 life_(&ptr_) {}
349 template <typename T, std::size_t N, typename E = element_type,
350 typename std::enable_if<!std::is_pointer<T>::value &&
351 !std::is_reference<T>::value &&
352 std::is_const<E>::value,
353 std::nullptr_t>::type = nullptr>
354 wrap(const wrap<T[N]> &array)
355 : ptr_(&array.base_[0]), observer_(array.life_.observer()),
356 life_(&ptr_) {}
357
361 template <typename T, std::size_t N>
362 wrap(const wrap<T (&)[N]> &array)
363 : ptr_(&array.ptr_[0][0]), observer_(array.observer_), life_(&ptr_) {}
364
368 wrap(std::nullptr_t = nullptr) noexcept
369 : ptr_(nullptr), observer_(nullptr), life_(&ptr_) {}
370
374 wrap(const wrap &other)
375 : ptr_(other.ptr_), observer_(other.observer_), life_(&ptr_) {}
379 wrap &operator=(const wrap &other) {
380 ptr_ = other.ptr_;
381 observer_ = other.observer_;
382 return *this;
383 }
384 ~wrap() = default;
385
389 template <typename T>
390 wrap(const wrap<T *> &ref)
391 : ptr_(ref.ptr_), observer_(ref.observer_), life_(&ptr_) {}
392
393 template <typename T>
394 friend class wrap;
395
403 template <typename E = element_type, typename = internal::skip_trace_tag>
405 static std::string func = type_name() + "::operator*()";
406 return wrap<E &>(assert_ptr(func), observer_);
407 }
415 template <typename = internal::skip_trace_tag>
416 element_type *operator->() const {
417 static std::string func = type_name() + "::operator->()";
418 return assert_ptr(func);
419 }
420
422 ++ptr_;
423 return *this;
424 }
426 wrap copy = *this;
427 ++ptr_;
428 return copy;
429 }
431 --ptr_;
432 return *this;
433 }
435 wrap copy = *this;
436 --ptr_;
437 return copy;
438 }
439 wrap &operator+=(std::ptrdiff_t n) {
440 ptr_ += n;
441 return *this;
442 }
443 wrap &operator-=(std::ptrdiff_t n) {
444 ptr_ -= n;
445 return *this;
446 }
447 wrap operator+(std::ptrdiff_t n) const { return wrap(ptr_ + n, observer_); }
448 wrap operator-(std::ptrdiff_t n) const { return wrap(ptr_ - n, observer_); }
449 std::ptrdiff_t operator-(const wrap &other) const {
450 return ptr_ - other.ptr_;
451 }
458 template <typename E = element_type, typename = internal::skip_trace_tag>
459 wrap<E &> operator[](std::ptrdiff_t n) const {
460 static std::string func = type_name() + "::operator[]()";
461 return wrap<E &>((*this + n).assert_ptr(func), observer_);
462 }
463
467 operator element_type *() const noexcept { return ptr_; }
468
470 return wrap<element_type **>(&ptr_, life_.observer());
471 }
473 return wrap<element_type *const *>(&ptr_, life_.observer());
474 }
475};
476template <typename element_type>
477element_type *unwrap(const wrap<element_type *> &wrapper) noexcept {
478 return static_cast<element_type *>(wrapper);
479}
480
481template <typename element_type>
483template <typename element_type>
485
486template <typename element_type>
488template <typename element_type>
490template <typename element_type>
492template <typename element_type>
494
495} // namespace y3c
固定長配列 (std::array)
Definition array.h:20
ライフタイムの状態を観測するクラス
Definition life.h:89
element_type * assert_ptr(element_type *ptr, const std::string &func, internal::skip_trace_tag={}) const
Definition life.h:113
オブジェクトのライフタイムを管理するクラス
Definition life.h:207
life_observer observer() const
Definition life.h:233
ポインタ型wrap: element_type型のデータへのポインタと、 このポインタ自体の生存状態を管理するクラス
Definition wrap.h:318
wrap & operator=(const wrap &other)
ポインタのコピー
Definition wrap.h:379
wrap< E & > operator[](std::ptrdiff_t n) const
要素アクセス
Definition wrap.h:459
wrap & operator+=(std::ptrdiff_t n)
Definition wrap.h:439
wrap< E & > operator*() const
要素アクセス
Definition wrap.h:404
wrap & operator++()
Definition wrap.h:421
wrap(std::nullptr_t=nullptr) noexcept
デフォルトコンストラクタ: nullptrを指す
Definition wrap.h:368
wrap operator--(int)
Definition wrap.h:434
wrap(const wrap &other)
ポインタのコピー
Definition wrap.h:374
wrap(const wrap< T * > &ref)
別の型のポインタからの変換
Definition wrap.h:390
wrap & operator-=(std::ptrdiff_t n)
Definition wrap.h:443
wrap(const wrap< T(&)[N]> &array)
配列の参照型wrapからのキャスト
Definition wrap.h:362
wrap & operator--()
Definition wrap.h:430
element_type * operator->() const
メンバアクセス
Definition wrap.h:416
std::ptrdiff_t operator-(const wrap &other) const
Definition wrap.h:449
wrap(const wrap< T[N]> &array)
配列型wrapからのキャスト(const)
Definition wrap.h:354
wrap operator-(std::ptrdiff_t n) const
Definition wrap.h:448
wrap operator+(std::ptrdiff_t n) const
Definition wrap.h:447
wrap(element_type *ptr, internal::life_observer observer) noexcept
Definition wrap.h:333
wrap< element_type *const * > operator&() const
Definition wrap.h:472
wrap operator++(int)
Definition wrap.h:425
wrap< element_type ** > operator&()
Definition wrap.h:469
wrap(wrap< T[N]> &array)
配列型wrapからのキャスト
Definition wrap.h:343
参照型wrap: element_type型のデータへの参照を持つクラス
Definition wrap.h:168
wrap & operator=(const wrap &other)
コピー代入: 値を参照先へコピーする
Definition wrap.h:235
wrap(const wrap &) noexcept=default
コピーコンストラクタ: 同じものを参照する
wrap & operator=(wrap &&other)
ムーブ代入
Definition wrap.h:248
wrap< element_type * > operator&() const noexcept
Definition wrap.h:291
wrap(const wrap< T > &wrapper)
値型wrapの参照(const)
Definition wrap.h:207
wrap< E & > operator[](std::ptrdiff_t i)
element_typeが E[N] の形の場合、要素への参照を返す
Definition wrap.h:286
wrap(const wrap< T & > &ref) noexcept
参照型wrapのコピー: 同じものを参照する
Definition wrap.h:214
wrap & operator=(V &&args)
参照先への代入
Definition wrap.h:221
wrap(wrap< T > &wrapper)
値型wrapの参照
Definition wrap.h:196
wrap(element_type *ptr, internal::life_observer observer) noexcept
Definition wrap.h:186
値型wrap: base_type型のデータと、このデータの生存状態を管理するクラス
Definition wrap.h:26
wrap & operator=(const wrap &other)
コピー代入
Definition wrap.h:58
wrap(wrap &&other)
ムーブコンストラクタ
Definition wrap.h:54
wrap< const E & > operator[](std::ptrdiff_t i) const
base_typeが E[N] の形の場合、要素への参照を返す(const)
Definition wrap.h:126
internal::life life_
Definition wrap.h:38
wrap< base_type * > operator&()
Definition wrap.h:132
wrap< const base_type * > operator&() const
Definition wrap.h:135
wrap & operator=(V &&args)
引数はそのままbase_typeのoperator=()に渡される。
Definition wrap.h:82
wrap(const wrap &other)
コピーコンストラクタ
Definition wrap.h:48
~wrap()=default
wrap & operator=(wrap &&other)
ムーブ代入
Definition wrap.h:67
wrap()
デフォルト構築
Definition wrap.h:44
wrap< E & > operator[](std::ptrdiff_t i)
base_typeが E[N] の形の場合、要素への参照を返す
Definition wrap.h:110
wrap(Args &&...args)
コンストラクタ引数はそのままbase_typeのコンストラクタに渡される。
Definition wrap.h:77
base_type base_
Definition wrap.h:37
Definition array.h:8
std::array< T, N > & unwrap(array< T, N > &wrapper) noexcept
Definition array.h:372
Definition terminate.h:27