kblib 0.2.3
General utilities library for modern C++
memory.h
Go to the documentation of this file.
1/* *****************************************************************************
2 * kblib is a general utility library for C++14 and C++17, intended to provide
3 * performant high-level abstractions and more expressive ways to do simple
4 * things.
5 *
6 * Copyright (c) 2021 killerbee
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 * ****************************************************************************/
21
32#ifndef MEMORY_H
33#define MEMORY_H
34
35#include "algorithm.h"
36#include "tdecl.h"
37
38#include <utility>
39#include <vector>
40
41namespace KBLIB_NS {
42
43template <typename T, bool = std::is_class<T>::value>
45 null_construct() noexcept(std::is_nothrow_default_constructible<T>::value)
46 : t{} {}
47
48 T t;
49
50 operator T&() noexcept { return t; }
51 operator const T&() const noexcept { return t; }
52};
53
54template <typename T>
55struct null_construct<T, true> : public T {
56 null_construct() noexcept(std::is_nothrow_default_constructible<T>::value)
57 : T{} {}
58};
59
60#if __cpp_nontype_template_parameter_auto
61template <auto FunPtr>
62struct fun_ptr_deleter;
63
64template <typename Arg, void (*FunPtr)(Arg)>
65struct fun_ptr_deleter<FunPtr> {
66 auto operator()(Arg arg) const -> void { return FunPtr(arg); }
67};
68#endif
69
70namespace detail_memory {
71
72 template <typename D, typename T, typename V = void>
74 using type = T*;
75 };
76
77 template <typename D, typename T>
78 struct filter_deleter_pointer<D, T, void_t<typename D::pointer>> {
79 using type = typename std::remove_reference<D>::type::pointer;
80 };
81
82 template <typename D, typename T>
84
85 template <typename T,
86 bool = std::is_class<T>::value and not std::is_final<T>::value,
87 bool
88 = std::is_object<typename std::remove_reference<T>::type>::value>
90
91 template <typename T>
92 struct as_base_class<T, false, true> {
94 auto base() noexcept -> T& { return base_; }
95 auto base() const noexcept -> const T& { return base_; }
96 explicit operator T&() noexcept { return base(); }
97 explicit operator const T&() const noexcept { return base(); }
98 };
99
100 template <typename T>
101 struct as_base_class<T, true, true> : T {
102 auto base() noexcept -> T& { return *this; }
103 auto base() const noexcept -> const T& { return *this; }
104 using T::T;
105 as_base_class(const T& t,
106 enable_if_t<std::is_copy_constructible<T>::value,
107 as_base_class*> = nullptr) //
108 noexcept(std::is_nothrow_copy_constructible<T>::value)
109 : T(t) {}
110 as_base_class(T&& t, enable_if_t<std::is_move_constructible<T>::value,
111 as_base_class*> = nullptr) //
112 noexcept(std::is_nothrow_move_constructible<T>::value)
113 : T(std::move(t)) {}
114 };
115
116#if KBLIB_USE_CXX17
117 template <typename R, typename A, bool E>
118 struct as_base_class<R (&)(A) noexcept(E), false, false> {
119 using type = R(A) noexcept(E);
121 auto base() const noexcept -> type& { return *base_; }
122 explicit operator type&() const noexcept { return base(); }
123 };
124#else
125 template <typename R, typename A>
126 struct as_base_class<R (&)(A), false, false> {
127 using type = R(A);
128 type* base_;
129 auto base() const noexcept -> type& { return *base_; }
130 explicit operator type&() const noexcept { return base(); }
131 };
132#endif
133
134 template <typename T>
135 struct as_base_class<T&, false, true> {
136 std::reference_wrapper<T> base_;
137
138 auto base() noexcept -> T& { return base_; }
139 auto base() const noexcept -> const T& { return base_; }
140
141 explicit operator T&() noexcept { return base(); }
142 explicit operator const T&() const noexcept { return base(); }
143 };
144
145 struct noop_t {
146 auto operator()() const noexcept -> void {}
147 };
148 struct value_init {};
149
150 template <typename T, typename Construct = noop_t, typename Destroy = noop_t>
152 template <typename... Args>
153 rule_zero(Args&&... args)
154 : as_base_class<T>(std::forward<Args>(args)...) {}
155 };
156
157 template <typename T, typename D>
159 : as_base_class<T>
160 , as_base_class<D> {
161 on_destroy() noexcept = default;
162 on_destroy(const on_destroy&) noexcept(
163 std::is_nothrow_copy_constructible<T>::value and
164 std::is_nothrow_copy_constructible<D>::value)
165 = default;
167 std::is_nothrow_move_constructible<T>::value and
168 std::is_nothrow_move_constructible<D>::value)
169 = default;
170 on_destroy& operator=(const on_destroy&) noexcept(
171 std::is_nothrow_copy_assignable<T>::value and
172 std::is_nothrow_copy_assignable<D>::value)
173 = default;
174 on_destroy& operator=(on_destroy&&) noexcept(
175 std::is_nothrow_move_assignable<T>::value and
176 std::is_nothrow_move_assignable<D>::value)
177 = default;
178
179 using as_base_class<T>::base;
180 operator T&() noexcept { return base(); }
181 operator const T&() const noexcept { return base(); }
182
184 (invoke)(static_cast<D&&>(*this), static_cast<T&&>(*this));
185 }
186 };
187
188} // namespace detail_memory
189
190template <typename T>
191class live_ptr;
192
193template <typename T>
195 public:
199
201
202 struct _destroy {
203 auto operator()(std::vector<live_wrapper**>&& self) const noexcept
204 -> void {
205 for (auto p : self) {
206 if (p) {
207 *p = nullptr;
208 }
209 }
210 }
211 };
212
215 _observers{};
216};
217
218template <typename T>
219class live_wrapper<const T> : public live_wrapper<T> {};
220
221namespace detail_memory {
222
223 template <typename T>
225 template <template <typename T> class C, typename T>
226 struct template_param<C<T>> {
227 using type = T;
228 };
229
230 template <typename D>
232 private:
233 using T = typename template_param<D>::type;
234 using mT = typename std::remove_const<T>::type;
235
236 public:
237 auto operator*() noexcept -> T& { return obj->data; }
238 auto operator*() const noexcept -> const T& { return obj->data; }
239
240 auto operator->() noexcept -> T* { return &obj->data; }
241 auto operator->() const noexcept -> const T* { return &obj->data; }
242
243 operator bool() const noexcept { return obj; }
244
245 friend auto operator==(const D& lhs, std::nullptr_t) -> bool {
246 return not lhs;
247 }
248 friend auto operator==(std::nullptr_t, const D& rhs) -> bool {
249 return not rhs;
250 }
251
252 friend auto operator==(const D& lhs, const D& rhs) -> bool {
253 return lhs.obj == rhs.obj;
254 }
255
256 friend auto operator==(const D& lhs, const T* rhs) -> bool {
257 if (not lhs and not rhs) {
258 return true;
259 } else {
260 return lhs and &lhs.obj->data == rhs;
261 }
262 }
263 friend auto operator==(const T* lhs, const D& rhs) -> bool {
264 if (not rhs and not lhs) {
265 return true;
266 } else {
267 return rhs and &rhs.obj->data == lhs;
268 }
269 }
270
271 live_ptr_base() noexcept = default;
273 : obj{p} {
274 add();
275 }
276 auto operator=(const live_ptr_base& o) noexcept -> live_ptr_base& {
277 rem();
278 obj = o.obj;
279 add();
280 return *this;
281 }
282 auto operator=(live_ptr_base&& o) noexcept -> live_ptr_base& {
283 rem();
284 move(o);
285 return *this;
286 }
287
289 : obj{o.obj} {
290 add();
291 }
292 live_ptr_base(live_ptr_base&& o) noexcept { move(o.as_D()); }
293 ~live_ptr_base() { rem(); }
294
295 auto operator=(const D& o) -> D& {
296 rem();
297 obj = o.obj;
298 add();
299 return as_D();
300 }
301 auto operator=(D&& o) noexcept -> D& {
302 this->rem();
303 this->move(o);
304 return as_D();
305 }
306
307 protected:
308 auto add() -> void { obj->_observers.base().push_back(&obj); }
309 auto rem() -> void {
310 if (obj) {
311 erase(obj->_observers.base(), &obj);
312 }
313 }
314 auto move(D& o) -> void {
315 if ((obj = std::exchange(o.obj, nullptr))) {
316 std::replace(obj->_observers.base().begin(),
317 obj->_observers.base().end(), &o.obj, &obj);
318 }
319 }
320 mutable live_wrapper<mT>* obj = nullptr;
321
322 private:
323 auto as_D() noexcept -> D& { return static_cast<D&>(*this); }
324 auto as_D() const noexcept -> const D& {
325 return static_cast<const D&>(*this);
326 }
327 };
328} // namespace detail_memory
329
330template <typename T>
331class live_ptr : public detail_memory::live_ptr_base<live_ptr<T>> {
333
334 public:
335 using value_type = T;
336
337 live_ptr() = default;
338 live_ptr(const live_ptr& o) = default;
339 live_ptr(live_ptr&& o) noexcept = default;
340 auto operator=(const live_ptr& o) -> live_ptr& = default;
341 auto operator=(live_ptr&& o) noexcept -> live_ptr& = default;
342
344 : base{&o} {
345 this->add();
346 }
348 this->rem();
349 this->obj = &o;
350 this->add();
351 return *this;
352 }
353
354 ~live_ptr() = default;
355
356 private:
357 friend class live_ptr<const T>;
358};
359
360template <typename mT>
361class live_ptr<const mT>
362 : public detail_memory::live_ptr_base<live_ptr<const mT>> {
364
365 public:
366 using T = const mT;
367 using value_type = T;
368 live_ptr() = default;
369 live_ptr(const live_ptr<T>& o) = default;
371 : base{o.obj} {}
372 live_ptr(live_ptr<T>&& o) noexcept = default;
373 live_ptr(live_ptr<mT>&& o) noexcept { this->move(o); }
374 auto operator=(const live_ptr<T>& o) -> live_ptr& = default;
375 auto operator=(live_ptr<T>&& o) noexcept -> live_ptr& = default;
376
377 auto operator=(const live_ptr<mT>& o) -> live_ptr& {
378 this->obj = o.obj;
379 this->add();
380 return *this;
381 }
382 auto operator=(live_ptr<mT>&& o) noexcept -> live_ptr& {
383 this->obj = o.obj;
384 this->add();
385 return *this;
386 }
387
388 explicit live_ptr(const live_wrapper<mT>& o)
389 : base{&o} {
390 this->add();
391 }
393 this->rem();
394 this->obj = &o;
395 this->add();
396 return *this;
397 }
398
399 ~live_ptr() = default;
400};
401
402template <typename T>
404 return live_ptr<T>{*this};
405}
406
407template <typename T>
409 return live_ptr<const T>{*this};
410}
411
412template <typename T>
414 return live_ptr<const T>{*this};
415}
416
417// cond_ptr: A pointer which can either uniquely own its referent, or which can
418// be a non-owning reference. Note that custom deleter support is not present;
419// however it will not implicitly strip a deleter from a unique_ptr.
420
421template <typename T, typename Deleter = std::default_delete<T>>
422class cond_ptr : private detail_memory::as_base_class<Deleter> {
424
425 public:
427 using element_type = T;
428 using deleter_type = Deleter;
429
430#if 0
431 static_assert(std::is_nothrow_invocable<Deleter&, pointer>::value,
432 "cond_ptr<T> requires that get_deleter not throw exceptions.");
433#endif
434
435 using unique = std::unique_ptr<T, Deleter>;
436
437 cond_ptr() noexcept = default;
438 cond_ptr(std::nullptr_t) noexcept {}
439
440 explicit cond_ptr(T* p, bool owner = false,
441 std::decay_t<Deleter> del = {}) noexcept
442 : d_base{std::move(del)}
443 , ptr_(p)
444 , owns_(owner) {}
445 explicit cond_ptr(T* p, std::decay_t<Deleter> del) noexcept
446 : d_base{std::move(del)}
447 , ptr_(p) {}
448
449 cond_ptr(unique&& p) noexcept
450 : d_base{p.get_deleter()}
451 , ptr_(p.release())
452 , owns_(ptr_) {}
453
454 cond_ptr(const cond_ptr& other) = delete;
455 // cond_ptr(const cond_ptr& other) noexcept
456 // : d_base{other.get_deleter()}, ptr_(other.ptr_) {}
457 cond_ptr(cond_ptr&& other) noexcept
458 : d_base{other.get_deleter()}
459 , ptr_(other.ptr_)
460 , owns_(std::exchange(other.owns_, false)) {}
461
462 KBLIB_NODISCARD static auto adopt(T* p) noexcept -> cond_ptr {
463 return {p, true};
464 }
465 KBLIB_NODISCARD static auto adopt(T* p, deleter_type del) noexcept
466 -> cond_ptr {
467 return {p, true, del};
468 }
469
470 auto operator=(const cond_ptr& rhs) & -> cond_ptr& = delete;
471 // auto operator=(const cond_ptr& rhs) & noexcept -> cond_ptr& {
472 // if (owns_) {
473 // get_deleter()(ptr_);
474 // }
475 // owns_ = false;
476 // ptr_ = rhs.release();
477 // return *this;
478 // }
479 auto operator=(cond_ptr&& rhs) & noexcept -> cond_ptr& {
480 if (owns_) {
481 get_deleter()(ptr_);
482 }
483 owns_ = rhs.owns();
484 static_cast<d_base&>(*this) = {std::move(rhs.get_deleter())};
485 ptr_ = rhs.release();
486 return *this;
487 }
488 auto operator=(unique&& rhs) -> cond_ptr& {
489 static_cast<d_base&>(*this) = {std::move(rhs.get_deleter())};
490 ptr_ = rhs.release();
491 owns_ = bool(ptr_);
492 return *this;
493 }
494
505 KBLIB_NODISCARD auto to_unique() && noexcept -> unique {
506 if (owns_) {
507 return {release(), std::move(get_deleter())};
508 } else {
509 return {nullptr, get_deleter()};
510 }
511 }
512
513 explicit operator unique() && noexcept {
514 return std::move(*this).to_unique();
515 }
516
517 ~cond_ptr() noexcept {
518 if (owns_ and ptr_) {
519 get_deleter()(ptr_);
520 }
521 }
522
523 KBLIB_NODISCARD auto weak() const& noexcept -> cond_ptr {
524 return cond_ptr{ptr_, false};
525 }
526
527 KBLIB_NODISCARD auto owns() const noexcept -> bool { return owns_; }
528 KBLIB_NODISCARD auto release() & noexcept -> T* {
529 owns_ = false;
530 return std::exchange(ptr_, nullptr);
531 }
532
533 KBLIB_NODISCARD auto get_deleter() noexcept -> Deleter& {
534 return this->d_base::base();
535 }
536
537 KBLIB_NODISCARD auto get_deleter() const noexcept -> const Deleter& {
538 return this->d_base::base();
539 }
540
541 auto reset(T* p = nullptr, bool owner = false,
542 std::decay_t<Deleter> del = {}) & noexcept -> void {
543 if (owns_) {
544 get_deleter()(ptr_);
545 }
546 ptr_ = p;
547 owns_ = owner;
548 get_deleter() = std::move(del);
549 }
550 auto reset(T* p, std::decay_t<Deleter> del = {}) & noexcept -> void {
551 if (owns_) {
552 get_deleter()(ptr_);
553 }
554 ptr_ = p;
555 owns_ = false;
556 get_deleter() = std::move(del);
557 }
558
559 auto swap(cond_ptr& other) noexcept(
561 using std::swap;
562 swap(ptr_, other.ptr_);
563 swap(owns_, other.owns_);
564 swap(get_deleter(), other.get_deleter());
565 }
566
567 KBLIB_NODISCARD auto get() & noexcept -> T* { return ptr_; }
568
569 KBLIB_NODISCARD auto get() const& noexcept -> const T* { return ptr_; }
570
571 KBLIB_NODISCARD explicit operator bool() const noexcept { return ptr_; }
572
573 KBLIB_NODISCARD auto operator*() & noexcept -> T& { return *ptr_; }
574
575 KBLIB_NODISCARD auto operator*() const& noexcept -> const T& {
576 return *ptr_;
577 }
578
579 KBLIB_NODISCARD auto operator->() & noexcept -> T* { return ptr_; }
580
581 KBLIB_NODISCARD auto operator->() const& noexcept -> const T* {
582 return ptr_;
583 }
584
585 KBLIB_NODISCARD friend constexpr auto operator==(
586 const cond_ptr& lhs, const cond_ptr& rhs) noexcept -> bool {
587 return lhs.ptr_ == rhs.ptr_;
588 }
589
590 KBLIB_NODISCARD friend constexpr auto operator==(
591 const unique& lhs, const cond_ptr& rhs) noexcept -> bool {
592 return lhs.get() == rhs.ptr_;
593 }
594
595 KBLIB_NODISCARD friend constexpr auto operator==(const cond_ptr& lhs,
596 const unique& rhs) noexcept
597 -> bool {
598 return lhs.ptr_ == rhs.get();
599 }
600
601 private:
602 T* ptr_ = nullptr;
603 bool owns_ = false;
604};
605
606template <typename T, typename Deleter>
607class cond_ptr<T[], Deleter> : private detail_memory::as_base_class<Deleter> {
609
610 public:
612 using element_type = T;
613 using deleter_type = Deleter;
614
615#if 0
616 static_assert(std::is_nothrow_invocable<Deleter&, pointer>::value,
617 "cond_ptr<T[]> requires that deleter not throw exceptions.");
618#endif
619
620 using unique = std::unique_ptr<T[], Deleter>;
621
622 cond_ptr() noexcept = default;
623 cond_ptr(std::nullptr_t) noexcept {}
624
625 explicit cond_ptr(T* p, bool owner = false,
626 std::decay_t<Deleter> del = {}) noexcept
627 : d_base{std::move(del)}
628 , ptr_(p)
629 , owns_(owner) {}
630 explicit cond_ptr(T* p, std::decay_t<Deleter> del) noexcept
631 : d_base{std::move(del)}
632 , ptr_(p) {}
633
634 cond_ptr(unique&& p) noexcept
635 : d_base{p.get_deleter()}
636 , ptr_(p.release())
637 , owns_(ptr_) {}
638
639 cond_ptr(const cond_ptr& other) = delete;
640 // cond_ptr(const cond_ptr& other) noexcept
641 // : d_base{other.get_deleter()}, ptr_(other.ptr_) {}
642 cond_ptr(cond_ptr&& other) noexcept
643 : d_base{other.get_deleter()}
644 , ptr_(other.ptr_)
645 , owns_(std::exchange(other.owns_, false)) {}
646
647 KBLIB_NODISCARD static auto adopt(T* p) noexcept -> cond_ptr {
648 return {p, true};
649 }
650 KBLIB_NODISCARD static auto adopt(T* p, deleter_type del) noexcept
651 -> cond_ptr {
652 return {p, true, del};
653 }
654
655 auto operator=(const cond_ptr& rhs) & -> cond_ptr& = delete;
656 // auto operator=(const cond_ptr& rhs) & noexcept -> cond_ptr& {
657 // if (owns_) {
658 // get_deleter()(ptr_);
659 // }
660 // owns_ = false;
661 // ptr_ = rhs.release();
662 // return *this;
663 // }
664 auto operator=(cond_ptr&& rhs) & noexcept -> cond_ptr& {
665 if (owns_) {
666 get_deleter()(ptr_);
667 }
668 owns_ = rhs.owns();
669 ptr_ = rhs.release();
670 return *this;
671 }
672 auto operator=(unique&& rhs) -> cond_ptr& {
673 ptr_ = rhs.release();
674 owns_ = bool(ptr_);
675 get_deleter() = std::move(rhs.get_deleter());
676 return *this;
677 }
678
689 KBLIB_NODISCARD auto to_unique() && noexcept -> unique {
690 if (owns_) {
691 return {release(), get_deleter()};
692 } else {
693 return nullptr;
694 }
695 }
696
697 explicit operator unique() && noexcept {
698 return std::move(*this).to_unique();
699 }
700
701 ~cond_ptr() noexcept {
702 if (owns_) {
703 get_deleter()(ptr_);
704 }
705 }
706
707 KBLIB_NODISCARD auto weak() const& noexcept -> cond_ptr {
708 return cond_ptr{ptr_, false};
709 }
710
711 KBLIB_NODISCARD auto owns() const noexcept -> bool { return owns_; }
712 KBLIB_NODISCARD auto release() & noexcept -> T* {
713 owns_ = false;
714 return std::exchange(ptr_, nullptr);
715 }
716
717 KBLIB_NODISCARD auto get_deleter() noexcept -> Deleter& { return *this; }
718
719 KBLIB_NODISCARD auto get_deleter() const noexcept -> const Deleter& {
720 return *this;
721 }
722
723 auto reset(T* p = nullptr, bool owner = false,
724 std::decay_t<Deleter> del = {}) & noexcept -> void {
725 if (owns_) {
726 get_deleter()(ptr_);
727 }
728 ptr_ = p;
729 owns_ = owner;
730 get_deleter() = std::move(del);
731 }
732 auto reset(T* p, std::decay_t<Deleter> del = {}) & noexcept -> void {
733 if (owns_) {
734 get_deleter()(ptr_);
735 }
736 ptr_ = p;
737 owns_ = false;
738 get_deleter() = std::move(del);
739 }
740
741 auto swap(cond_ptr& other) -> void {
742 std::swap(ptr_, other.ptr_);
743 std::swap(owns_, other.owns_);
744 std::swap(get_deleter(), other.get_deleter());
745 }
746
747 KBLIB_NODISCARD auto get() & noexcept -> T* { return ptr_; }
748
749 KBLIB_NODISCARD auto get() const& noexcept -> const T* { return ptr_; }
750
751 explicit operator bool() const noexcept { return ptr_; }
752
753 KBLIB_NODISCARD T& operator[](std::size_t index) & noexcept {
754 return ptr_[index];
755 }
756
757 KBLIB_NODISCARD const T& operator[](std::size_t index) const& noexcept {
758 return ptr_[index];
759 }
760
761 KBLIB_NODISCARD friend constexpr auto operator==(
762 const cond_ptr& lhs, const cond_ptr& rhs) noexcept -> bool {
763 return lhs.ptr_ == rhs.ptr_;
764 }
765
766 KBLIB_NODISCARD friend constexpr auto operator==(
767 const unique& lhs, const cond_ptr& rhs) noexcept -> bool {
768 return lhs.get() == rhs.ptr_;
769 }
770
771 KBLIB_NODISCARD friend constexpr auto operator==(const cond_ptr& lhs,
772 const unique& rhs) noexcept
773 -> bool {
774 return lhs.ptr_ == rhs.get();
775 }
776
777 private:
778 T* ptr_ = nullptr;
779 bool owns_ = false;
780};
781
782template <typename T, typename Deleter>
783KBLIB_NODISCARD auto make_cond_ptr(std::unique_ptr<T, Deleter>&& arg) noexcept
785 return cond_ptr<T>(std::move(arg));
786}
787
788template <typename T>
789KBLIB_NODISCARD auto make_cond_ptr(T* arg, bool owner = false) noexcept
790 -> cond_ptr<T> {
791 return cond_ptr<T>(arg, owner);
792}
793
794template <typename T, typename Deleter>
795KBLIB_NODISCARD auto make_cond_ptr(T* arg, Deleter del) noexcept
797 return cond_ptr<T, Deleter>(arg, del);
798}
799
800template <typename T, typename Deleter>
801KBLIB_NODISCARD auto make_cond_ptr(T* arg, bool owner, Deleter del) noexcept
803 return cond_ptr<T, Deleter>(arg, owner, del);
804}
805
806} // namespace KBLIB_NS
807
808#endif // MEMORY_H
Provides general-purpose algorithms, similar to the <algorithms> header.
cond_ptr(cond_ptr &&other) noexcept
Definition: memory.h:642
auto get_deleter() const noexcept -> const Deleter &
Definition: memory.h:719
auto release() &noexcept -> T *
Definition: memory.h:712
static auto adopt(T *p, deleter_type del) noexcept -> cond_ptr
Definition: memory.h:650
auto operator=(unique &&rhs) -> cond_ptr &
Definition: memory.h:672
auto swap(cond_ptr &other) -> void
Definition: memory.h:741
cond_ptr(T *p, std::decay_t< Deleter > del) noexcept
Definition: memory.h:630
detail_memory::filter_deleter_pointer_t< Deleter, T > pointer
Definition: memory.h:611
auto get_deleter() noexcept -> Deleter &
Definition: memory.h:717
const T & operator[](std::size_t index) const &noexcept
Definition: memory.h:757
T & operator[](std::size_t index) &noexcept
Definition: memory.h:753
auto operator=(cond_ptr &&rhs) &noexcept -> cond_ptr &
Definition: memory.h:664
cond_ptr(unique &&p) noexcept
Definition: memory.h:634
std::unique_ptr< T[], Deleter > unique
Definition: memory.h:620
auto get() &noexcept -> T *
Definition: memory.h:747
auto to_unique() &&noexcept -> unique
Transfers ownership to a unique_ptr if possible. If *this is not owning, returns nullptr.
Definition: memory.h:689
friend constexpr auto operator==(const unique &lhs, const cond_ptr &rhs) noexcept -> bool
Definition: memory.h:766
auto reset(T *p=nullptr, bool owner=false, std::decay_t< Deleter > del={}) &noexcept -> void
Definition: memory.h:723
auto weak() const &noexcept -> cond_ptr
Definition: memory.h:707
static auto adopt(T *p) noexcept -> cond_ptr
Definition: memory.h:647
auto reset(T *p, std::decay_t< Deleter > del={}) &noexcept -> void
Definition: memory.h:732
friend constexpr auto operator==(const cond_ptr &lhs, const unique &rhs) noexcept -> bool
Definition: memory.h:771
auto get() const &noexcept -> const T *
Definition: memory.h:749
cond_ptr(const cond_ptr &other)=delete
cond_ptr(T *p, bool owner=false, std::decay_t< Deleter > del={}) noexcept
Definition: memory.h:625
auto owns() const noexcept -> bool
Definition: memory.h:711
friend constexpr auto operator==(const cond_ptr &lhs, const cond_ptr &rhs) noexcept -> bool
Definition: memory.h:761
auto operator=(const cond_ptr &rhs) &-> cond_ptr &=delete
auto operator=(const cond_ptr &rhs) &-> cond_ptr &=delete
static auto adopt(T *p, deleter_type del) noexcept -> cond_ptr
Definition: memory.h:465
auto reset(T *p=nullptr, bool owner=false, std::decay_t< Deleter > del={}) &noexcept -> void
Definition: memory.h:541
auto operator*() const &noexcept -> const T &
Definition: memory.h:575
auto operator->() &noexcept -> T *
Definition: memory.h:579
auto operator*() &noexcept -> T &
Definition: memory.h:573
auto release() &noexcept -> T *
Definition: memory.h:528
std::unique_ptr< T, Deleter > unique
Definition: memory.h:435
auto owns() const noexcept -> bool
Definition: memory.h:527
cond_ptr(T *p, bool owner=false, std::decay_t< Deleter > del={}) noexcept
Definition: memory.h:440
~cond_ptr() noexcept
Definition: memory.h:517
auto swap(cond_ptr &other) noexcept(fakestd::is_nothrow_swappable< Deleter >::value) -> void
Definition: memory.h:559
cond_ptr(T *p, std::decay_t< Deleter > del) noexcept
Definition: memory.h:445
auto get() &noexcept -> T *
Definition: memory.h:567
Deleter deleter_type
Definition: memory.h:428
cond_ptr(const cond_ptr &other)=delete
auto get_deleter() noexcept -> Deleter &
Definition: memory.h:533
auto operator=(unique &&rhs) -> cond_ptr &
Definition: memory.h:488
auto operator=(cond_ptr &&rhs) &noexcept -> cond_ptr &
Definition: memory.h:479
auto get_deleter() const noexcept -> const Deleter &
Definition: memory.h:537
friend constexpr auto operator==(const unique &lhs, const cond_ptr &rhs) noexcept -> bool
Definition: memory.h:590
cond_ptr(unique &&p) noexcept
Definition: memory.h:449
auto get() const &noexcept -> const T *
Definition: memory.h:569
cond_ptr() noexcept=default
auto to_unique() &&noexcept -> unique
Transfers ownership to a unique_ptr if possible. If *this is not owning, returns nullptr.
Definition: memory.h:505
static auto adopt(T *p) noexcept -> cond_ptr
Definition: memory.h:462
auto operator->() const &noexcept -> const T *
Definition: memory.h:581
auto weak() const &noexcept -> cond_ptr
Definition: memory.h:523
detail_memory::filter_deleter_pointer_t< Deleter, T > pointer
Definition: memory.h:426
friend constexpr auto operator==(const cond_ptr &lhs, const unique &rhs) noexcept -> bool
Definition: memory.h:595
friend constexpr auto operator==(const cond_ptr &lhs, const cond_ptr &rhs) noexcept -> bool
Definition: memory.h:585
auto reset(T *p, std::decay_t< Deleter > del={}) &noexcept -> void
Definition: memory.h:550
cond_ptr(cond_ptr &&other) noexcept
Definition: memory.h:457
auto operator=(const live_ptr< mT > &o) -> live_ptr &
Definition: memory.h:377
live_ptr(const live_ptr< T > &o)=default
auto operator=(const live_ptr< T > &o) -> live_ptr &=default
auto operator=(live_ptr< T > &&o) noexcept -> live_ptr &=default
live_ptr(const live_ptr< mT > &o)
Definition: memory.h:370
live_ptr(live_ptr< mT > &&o) noexcept
Definition: memory.h:373
live_ptr(const live_wrapper< mT > &o)
Definition: memory.h:388
auto operator=(live_ptr< mT > &&o) noexcept -> live_ptr &
Definition: memory.h:382
live_ptr(live_ptr< T > &&o) noexcept=default
auto operator=(const live_wrapper< mT > &o) -> live_ptr &
Definition: memory.h:392
auto operator=(live_ptr &&o) noexcept -> live_ptr &=default
auto operator=(live_wrapper< T > &o) -> live_ptr &
Definition: memory.h:347
live_ptr(live_ptr &&o) noexcept=default
live_ptr()=default
live_ptr(const live_ptr &o)=default
auto operator=(const live_ptr &o) -> live_ptr &=default
live_ptr(live_wrapper< T > &o)
Definition: memory.h:343
live_ptr< T > ref()
Definition: memory.h:403
live_ptr< const T > cref() const
Definition: memory.h:413
live_ptr< const T > ref() const
Definition: memory.h:408
typename filter_deleter_pointer< D, T >::type filter_deleter_pointer_t
Definition: memory.h:83
typename make_void< Ts... >::type void_t
Definition: fakestd.h:179
constexpr auto exchange(T &obj, U &&new_value) -> T
Definition: fakestd.h:719
typename std::enable_if< B, T >::type enable_if_t
Definition: fakestd.h:54
struct kblib::@0 swap
constexpr auto invoke(F &&f, Args &&... args) noexcept(noexcept(detail::do_invoke(std::forward< F >(f), std::forward< Args >(args)...))) -> decltype(auto)
Definition: fakestd.h:131
constexpr auto erase(Container &c, const Elem &val) noexcept(noexcept(c.erase(std::remove(c.begin(), c.end(), val), c.end()))) -> void
Abbreviation of the erase-remove idiom as a free function.
Definition: algorithm.h:68
auto make_cond_ptr(T *arg, bool owner, Deleter del) noexcept -> cond_ptr< T, Deleter >
Definition: memory.h:801
Definition: bits.h:721
auto base() const noexcept -> const T &
Definition: memory.h:95
as_base_class(T &&t, enable_if_t< std::is_move_constructible< T >::value, as_base_class * >=nullptr) noexcept(std::is_nothrow_move_constructible< T >::value)
Definition: memory.h:110
auto base() const noexcept -> const T &
Definition: memory.h:103
as_base_class(const T &t, enable_if_t< std::is_copy_constructible< T >::value, as_base_class * >=nullptr) noexcept(std::is_nothrow_copy_constructible< T >::value)
Definition: memory.h:105
auto base() const noexcept -> const T &
Definition: memory.h:139
typename std::remove_reference< D >::type::pointer type
Definition: memory.h:79
auto operator->() const noexcept -> const T *
Definition: memory.h:241
friend auto operator==(const T *lhs, const D &rhs) -> bool
Definition: memory.h:263
auto operator->() noexcept -> T *
Definition: memory.h:240
friend auto operator==(const D &lhs, const D &rhs) -> bool
Definition: memory.h:252
live_ptr_base(const live_ptr_base &o)
Definition: memory.h:288
auto operator=(D &&o) noexcept -> D &
Definition: memory.h:301
friend auto operator==(std::nullptr_t, const D &rhs) -> bool
Definition: memory.h:248
auto operator=(live_ptr_base &&o) noexcept -> live_ptr_base &
Definition: memory.h:282
auto operator*() const noexcept -> const T &
Definition: memory.h:238
auto operator=(const live_ptr_base &o) noexcept -> live_ptr_base &
Definition: memory.h:276
auto operator=(const D &o) -> D &
Definition: memory.h:295
friend auto operator==(const D &lhs, const T *rhs) -> bool
Definition: memory.h:256
live_wrapper< mT > * obj
Definition: memory.h:320
friend auto operator==(const D &lhs, std::nullptr_t) -> bool
Definition: memory.h:245
auto operator*() noexcept -> T &
Definition: memory.h:237
live_ptr_base(live_ptr_base &&o) noexcept
Definition: memory.h:292
auto operator()() const noexcept -> void
Definition: memory.h:146
rule_zero(Args &&... args)
Definition: memory.h:153
auto operator()(std::vector< live_wrapper ** > &&self) const noexcept -> void
Definition: memory.h:203
null_construct() noexcept(std::is_nothrow_default_constructible< T >::value)
Definition: memory.h:56
null_construct() noexcept(std::is_nothrow_default_constructible< T >::value)
Definition: memory.h:45
Provides macros and basic templates used by the rest of kblib.
#define KBLIB_NS
Definition: tdecl.h:113
#define KBLIB_NODISCARD
This internal macro is used to provide a fallback for [[nodiscard]] in C++14.
Definition: tdecl.h:129