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 
41 namespace kblib {
42 
43 template <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 
54 template <typename T>
55 struct 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
61 template <auto FunPtr>
62 struct fun_ptr_deleter;
63 
64 template <typename Arg, void (*FunPtr)(Arg)>
65 struct fun_ptr_deleter<FunPtr> {
66  auto operator()(Arg arg) const -> void { return FunPtr(arg); }
67 };
68 #endif
69 
70 namespace 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>
89  struct as_base_class;
90 
91  template <typename T>
92  struct as_base_class<T, false, true> {
93  T base_;
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  };
105 
106 #if KBLIB_USE_CXX17
107  template <typename R, typename A, bool E>
108  struct as_base_class<R (&)(A) noexcept(E), false, false> {
109  using type = R(A) noexcept(E);
111  auto base() const noexcept -> type& { return *base_; }
112  explicit operator type&() const noexcept { return base(); }
113  };
114 #else
115  template <typename R, typename A>
116  struct as_base_class<R (&)(A), false, false> {
117  using type = R(A);
118  type* base_;
119  auto base() const noexcept -> type& { return *base_; }
120  explicit operator type&() const noexcept { return base(); }
121  };
122 #endif
123 
124  template <typename T>
125  struct as_base_class<T&, false, true> {
126  std::reference_wrapper<T> base_;
127 
128  auto base() noexcept -> T& { return base_; }
129  auto base() const noexcept -> const T& { return base_; }
130 
131  explicit operator T&() noexcept { return base(); }
132  explicit operator const T&() const noexcept { return base(); }
133  };
134 
135  struct noop_t {
136  auto operator()() const noexcept -> void {}
137  };
138  struct value_init {};
139 
140  template <typename T, typename Construct = noop_t, typename Destroy = noop_t>
141  struct rule_zero : as_base_class<T> {
142  template <typename... Args>
143  rule_zero(Args&&... args)
144  : as_base_class<T>(std::forward<Args>(args)...) {}
145  };
146 
147  template <typename T, typename D>
148  struct on_destroy
149  : as_base_class<T>
150  , as_base_class<D> {
151  on_destroy() noexcept = default;
152  on_destroy(const on_destroy&) noexcept(
153  std::is_nothrow_copy_constructible<T>::value and
154  std::is_nothrow_copy_constructible<D>::value)
155  = default;
156  on_destroy(on_destroy&&) noexcept(
157  std::is_nothrow_move_constructible<T>::value and
158  std::is_nothrow_move_constructible<D>::value)
159  = default;
160  on_destroy& operator=(const on_destroy&) noexcept(
161  std::is_nothrow_copy_assignable<T>::value and
162  std::is_nothrow_copy_assignable<D>::value)
163  = default;
164  on_destroy& operator=(on_destroy&&) noexcept(
165  std::is_nothrow_move_assignable<T>::value and
166  std::is_nothrow_move_assignable<D>::value)
167  = default;
168 
169  using as_base_class<T>::base;
170  operator T&() noexcept { return base(); }
171  operator const T&() const noexcept { return base(); }
172 
174  (invoke)(static_cast<D&&>(*this), static_cast<T&&>(*this));
175  }
176  };
177 
178 } // namespace detail_memory
179 
180 template <typename T>
181 class live_ptr;
182 
183 template <typename T>
185  public:
189 
190  T data;
191 
192  struct _destroy {
193  auto operator()(std::vector<live_wrapper**>&& self) const noexcept
194  -> void {
195  for (auto p : self) {
196  if (p) {
197  *p = nullptr;
198  }
199  }
200  }
201  };
202 
206 };
207 
208 template <typename T>
209 class live_wrapper<const T> : public live_wrapper<T> {};
210 
211 namespace detail_memory {
212 
213  template <typename T>
215  template <template <typename T> class C, typename T>
216  struct template_param<C<T>> {
217  using type = T;
218  };
219 
220  template <typename D>
221  struct live_ptr_base {
222  private:
223  using T = typename template_param<D>::type;
224  using mT = typename std::remove_const<T>::type;
225 
226  public:
227  auto operator*() noexcept -> T& { return obj->data; }
228  auto operator*() const noexcept -> const T& { return obj->data; }
229 
230  auto operator->() noexcept -> T* { return &obj->data; }
231  auto operator->() const noexcept -> const T* { return &obj->data; }
232 
233  operator bool() const noexcept { return obj; }
234 
235  friend auto operator==(const D& lhs, std::nullptr_t) -> bool {
236  return not lhs;
237  }
238  friend auto operator==(std::nullptr_t, const D& rhs) -> bool {
239  return not rhs;
240  }
241 
242  friend auto operator==(const D& lhs, const D& rhs) -> bool {
243  return lhs.obj == rhs.obj;
244  }
245 
246  friend auto operator==(const D& lhs, const T* rhs) -> bool {
247  if (not lhs and not rhs) {
248  return true;
249  } else {
250  return lhs and &lhs.obj->data == rhs;
251  }
252  }
253  friend auto operator==(const T* lhs, const D& rhs) -> bool {
254  if (not rhs and not lhs) {
255  return true;
256  } else {
257  return rhs and &rhs.obj->data == lhs;
258  }
259  }
260 
261  live_ptr_base() noexcept = default;
263  : obj{p} {
264  add();
265  }
266  auto operator=(const live_ptr_base& o) noexcept -> live_ptr_base& {
267  rem();
268  obj = o.obj;
269  add();
270  return *this;
271  }
272  auto operator=(live_ptr_base&& o) noexcept -> live_ptr_base& {
273  rem();
274  move(o);
275  return *this;
276  }
277 
279  : obj{o.obj} {
280  add();
281  }
282  live_ptr_base(live_ptr_base&& o) noexcept { move(o.as_D()); }
284 
285  auto operator=(const D& o) -> D& {
286  rem();
287  obj = o.obj;
288  add();
289  return as_D();
290  }
291  auto operator=(D&& o) noexcept -> D& {
292  this->rem();
293  this->move(o);
294  return as_D();
295  }
296 
297  protected:
298  auto add() -> void { obj->_observers.base().push_back(&obj); }
299  auto rem() -> void {
300  if (obj) {
301  erase(obj->_observers.base(), &obj);
302  }
303  }
304  auto move(D& o) -> void {
305  if ((obj = std::exchange(o.obj, nullptr))) {
306  std::replace(obj->_observers.base().begin(),
307  obj->_observers.base().end(), &o.obj, &obj);
308  }
309  }
310  mutable live_wrapper<mT>* obj = nullptr;
311 
312  private:
313  auto as_D() noexcept -> D& { return static_cast<D&>(*this); }
314  auto as_D() const noexcept -> const D& {
315  return static_cast<const D&>(*this);
316  }
317  };
318 } // namespace detail_memory
319 
320 template <typename T>
321 class live_ptr : public detail_memory::live_ptr_base<live_ptr<T>> {
323 
324  public:
325  using value_type = T;
326 
327  live_ptr() = default;
328  live_ptr(const live_ptr& o) = default;
329  live_ptr(live_ptr&& o) noexcept = default;
330  auto operator=(const live_ptr& o) -> live_ptr& = default;
331  auto operator=(live_ptr&& o) noexcept -> live_ptr& = default;
332 
334  : base{&o} {
335  this->add();
336  }
338  this->rem();
339  this->obj = &o;
340  this->add();
341  return *this;
342  }
343 
344  ~live_ptr() = default;
345 
346  private:
347  friend class live_ptr<const T>;
348 };
349 
350 template <typename mT>
351 class live_ptr<const mT>
352  : public detail_memory::live_ptr_base<live_ptr<const mT>> {
354 
355  public:
356  using T = const mT;
357  using value_type = T;
358  live_ptr() = default;
359  live_ptr(const live_ptr<T>& o) = default;
361  : base{o.obj} {}
362  live_ptr(live_ptr<T>&& o) noexcept = default;
363  live_ptr(live_ptr<mT>&& o) noexcept { this->move(o); }
364  auto operator=(const live_ptr<T>& o) -> live_ptr& = default;
365  auto operator=(live_ptr<T>&& o) noexcept -> live_ptr& = default;
366 
367  auto operator=(const live_ptr<mT>& o) -> live_ptr& {
368  this->obj = o.obj;
369  this->add();
370  return *this;
371  }
372  auto operator=(live_ptr<mT>&& o) noexcept -> live_ptr& {
373  this->obj = o.obj;
374  this->add();
375  return *this;
376  }
377 
378  explicit live_ptr(const live_wrapper<mT>& o)
379  : base{&o} {
380  this->add();
381  }
382  auto operator=(const live_wrapper<mT>& o) -> live_ptr& {
383  this->rem();
384  this->obj = &o;
385  this->add();
386  return *this;
387  }
388 
389  ~live_ptr() = default;
390 };
391 
392 template <typename T>
394  return live_ptr<T>{*this};
395 }
396 
397 template <typename T>
399  return live_ptr<const T>{*this};
400 }
401 
402 template <typename T>
404  return live_ptr<const T>{*this};
405 }
406 
407 // cond_ptr: A pointer which can either uniquely own its referent, or which can
408 // be a non-owning reference. Note that custom deleter support is not present;
409 // however it will not implicitly strip a deleter from a unique_ptr.
410 
411 template <typename T, typename Deleter = std::default_delete<T>>
412 class cond_ptr : private detail_memory::as_base_class<Deleter> {
414 
415  public:
417  using element_type = T;
418  using deleter_type = Deleter;
419 
420 #if 0
421  static_assert(std::is_nothrow_invocable<Deleter&, pointer>::value,
422  "cond_ptr<T> requires that get_deleter not throw exceptions.");
423 #endif
424 
425  using unique = std::unique_ptr<T, Deleter>;
426 
427  cond_ptr() noexcept = default;
428  cond_ptr(std::nullptr_t) noexcept {}
429 
430  explicit cond_ptr(T* p, bool owner = false,
431  std::decay_t<Deleter> del = {}) noexcept
432  : d_base{std::move(del)}
433  , ptr_(p)
434  , owns_(owner) {}
435  explicit cond_ptr(T* p, std::decay_t<Deleter> del) noexcept
436  : d_base{std::move(del)}
437  , ptr_(p) {}
438 
439  cond_ptr(unique&& p) noexcept
440  : d_base{p.get_deleter()}
441  , ptr_(p.release())
442  , owns_(ptr_) {}
443 
444  cond_ptr(const cond_ptr& other) = delete;
445  // cond_ptr(const cond_ptr& other) noexcept
446  // : d_base{other.get_deleter()}, ptr_(other.ptr_) {}
447  cond_ptr(cond_ptr&& other) noexcept
448  : d_base{other.get_deleter()}
449  , ptr_(other.ptr_)
450  , owns_(std::exchange(other.owns_, false)) {}
451 
452  KBLIB_NODISCARD static auto adopt(T* p) noexcept -> cond_ptr {
453  return {p, true};
454  }
455  KBLIB_NODISCARD static auto adopt(T* p, deleter_type del) noexcept
456  -> cond_ptr {
457  return {p, true, del};
458  }
459 
460  auto operator=(const cond_ptr& rhs) & -> cond_ptr& = delete;
461  // auto operator=(const cond_ptr& rhs) & noexcept -> cond_ptr& {
462  // if (owns_) {
463  // get_deleter()(ptr_);
464  // }
465  // owns_ = false;
466  // ptr_ = rhs.release();
467  // return *this;
468  // }
469  auto operator=(cond_ptr&& rhs) & noexcept -> cond_ptr& {
470  if (owns_) {
471  get_deleter()(ptr_);
472  }
473  owns_ = rhs.owns();
474  static_cast<d_base&>(*this) = {std::move(rhs.get_deleter())};
475  ptr_ = rhs.release();
476  return *this;
477  }
478  auto operator=(unique&& rhs) -> cond_ptr& {
479  static_cast<d_base&>(*this) = {std::move(rhs.get_deleter())};
480  ptr_ = rhs.release();
481  owns_ = bool(ptr_);
482  return *this;
483  }
484 
495  KBLIB_NODISCARD auto to_unique() && noexcept -> unique {
496  if (owns_) {
497  return {release(), std::move(get_deleter())};
498  } else {
499  return {nullptr, get_deleter()};
500  }
501  }
502 
503  explicit operator unique() && noexcept {
504  return std::move(*this).to_unique();
505  }
506 
507  ~cond_ptr() noexcept {
508  if (owns_ and ptr_) {
509  get_deleter()(ptr_);
510  }
511  }
512 
513  KBLIB_NODISCARD auto weak() const& noexcept -> cond_ptr {
514  return cond_ptr{ptr_, false};
515  }
516 
517  KBLIB_NODISCARD auto owns() const noexcept -> bool { return owns_; }
518  KBLIB_NODISCARD auto release() & noexcept -> T* {
519  owns_ = false;
520  return std::exchange(ptr_, nullptr);
521  }
522 
523  KBLIB_NODISCARD auto get_deleter() noexcept -> Deleter& {
524  return this->d_base::base();
525  }
526 
527  KBLIB_NODISCARD auto get_deleter() const noexcept -> const Deleter& {
528  return this->d_base::base();
529  }
530 
531  auto reset(T* p = nullptr, bool owner = false,
532  std::decay_t<Deleter> del = {}) & noexcept -> void {
533  if (owns_) {
534  get_deleter()(ptr_);
535  }
536  ptr_ = p;
537  owns_ = owner;
538  get_deleter() = std::move(del);
539  }
540  auto reset(T* p, std::decay_t<Deleter> del = {}) & noexcept -> void {
541  if (owns_) {
542  get_deleter()(ptr_);
543  }
544  ptr_ = p;
545  owns_ = false;
546  get_deleter() = std::move(del);
547  }
548 
549  auto swap(cond_ptr& other) noexcept(
551  using std::swap;
552  swap(ptr_, other.ptr_);
553  swap(owns_, other.owns_);
554  swap(get_deleter(), other.get_deleter());
555  }
556 
557  KBLIB_NODISCARD auto get() & noexcept -> T* { return ptr_; }
558 
559  KBLIB_NODISCARD auto get() const& noexcept -> const T* { return ptr_; }
560 
561  KBLIB_NODISCARD explicit operator bool() const noexcept { return ptr_; }
562 
563  KBLIB_NODISCARD auto operator*() & noexcept -> T& { return *ptr_; }
564 
565  KBLIB_NODISCARD auto operator*() const& noexcept -> const T& {
566  return *ptr_;
567  }
568 
569  KBLIB_NODISCARD auto operator->() & noexcept -> T* { return ptr_; }
570 
571  KBLIB_NODISCARD auto operator->() const& noexcept -> const T* {
572  return ptr_;
573  }
574 
575  KBLIB_NODISCARD friend constexpr auto operator==(
576  const cond_ptr& lhs, const cond_ptr& rhs) noexcept -> bool {
577  return lhs.ptr_ == rhs.ptr_;
578  }
579 
580  KBLIB_NODISCARD friend constexpr auto operator==(
581  const unique& lhs, const cond_ptr& rhs) noexcept -> bool {
582  return lhs.get() == rhs.ptr_;
583  }
584 
585  KBLIB_NODISCARD friend constexpr auto operator==(const cond_ptr& lhs,
586  const unique& rhs) noexcept
587  -> bool {
588  return lhs.ptr_ == rhs.get();
589  }
590 
591  private:
592  T* ptr_ = nullptr;
593  bool owns_ = false;
594 };
595 
596 template <typename T, typename Deleter>
597 class cond_ptr<T[], Deleter> : private detail_memory::as_base_class<Deleter> {
599 
600  public:
602  using element_type = T;
603  using deleter_type = Deleter;
604 
605 #if 0
606  static_assert(std::is_nothrow_invocable<Deleter&, pointer>::value,
607  "cond_ptr<T[]> requires that deleter not throw exceptions.");
608 #endif
609 
610  using unique = std::unique_ptr<T[], Deleter>;
611 
612  cond_ptr() noexcept = default;
613  cond_ptr(std::nullptr_t) noexcept {}
614 
615  explicit cond_ptr(T* p, bool owner = false,
616  std::decay_t<Deleter> del = {}) noexcept
617  : d_base{std::move(del)}
618  , ptr_(p)
619  , owns_(owner) {}
620  explicit cond_ptr(T* p, std::decay_t<Deleter> del) noexcept
621  : d_base{std::move(del)}
622  , ptr_(p) {}
623 
624  cond_ptr(unique&& p) noexcept
625  : d_base{p.get_deleter()}
626  , ptr_(p.release())
627  , owns_(ptr_) {}
628 
629  cond_ptr(const cond_ptr& other) = delete;
630  // cond_ptr(const cond_ptr& other) noexcept
631  // : d_base{other.get_deleter()}, ptr_(other.ptr_) {}
632  cond_ptr(cond_ptr&& other) noexcept
633  : d_base{other.get_deleter()}
634  , ptr_(other.ptr_)
635  , owns_(std::exchange(other.owns_, false)) {}
636 
637  KBLIB_NODISCARD static auto adopt(T* p) noexcept -> cond_ptr {
638  return {p, true};
639  }
640  KBLIB_NODISCARD static auto adopt(T* p, deleter_type del) noexcept
641  -> cond_ptr {
642  return {p, true, del};
643  }
644 
645  auto operator=(const cond_ptr& rhs) & -> cond_ptr& = delete;
646  // auto operator=(const cond_ptr& rhs) & noexcept -> cond_ptr& {
647  // if (owns_) {
648  // get_deleter()(ptr_);
649  // }
650  // owns_ = false;
651  // ptr_ = rhs.release();
652  // return *this;
653  // }
654  auto operator=(cond_ptr&& rhs) & noexcept -> cond_ptr& {
655  if (owns_) {
656  get_deleter()(ptr_);
657  }
658  owns_ = rhs.owns();
659  ptr_ = rhs.release();
660  return *this;
661  }
662  auto operator=(unique&& rhs) -> cond_ptr& {
663  ptr_ = rhs.release();
664  owns_ = bool(ptr_);
665  get_deleter() = std::move(rhs.get_deleter());
666  return *this;
667  }
668 
679  KBLIB_NODISCARD auto to_unique() && noexcept -> unique {
680  if (owns_) {
681  return {release(), get_deleter()};
682  } else {
683  return nullptr;
684  }
685  }
686 
687  explicit operator unique() && noexcept {
688  return std::move(*this).to_unique();
689  }
690 
691  ~cond_ptr() noexcept {
692  if (owns_) {
693  get_deleter()(ptr_);
694  }
695  }
696 
697  KBLIB_NODISCARD auto weak() const& noexcept -> cond_ptr {
698  return cond_ptr{ptr_, false};
699  }
700 
701  KBLIB_NODISCARD auto owns() const noexcept -> bool { return owns_; }
702  KBLIB_NODISCARD auto release() & noexcept -> T* {
703  owns_ = false;
704  return std::exchange(ptr_, nullptr);
705  }
706 
707  KBLIB_NODISCARD auto get_deleter() noexcept -> Deleter& { return *this; }
708 
709  KBLIB_NODISCARD auto get_deleter() const noexcept -> const Deleter& {
710  return *this;
711  }
712 
713  auto reset(T* p = nullptr, bool owner = false,
714  std::decay_t<Deleter> del = {}) & noexcept -> void {
715  if (owns_) {
716  get_deleter()(ptr_);
717  }
718  ptr_ = p;
719  owns_ = owner;
720  get_deleter() = std::move(del);
721  }
722  auto reset(T* p, std::decay_t<Deleter> del = {}) & noexcept -> void {
723  if (owns_) {
724  get_deleter()(ptr_);
725  }
726  ptr_ = p;
727  owns_ = false;
728  get_deleter() = std::move(del);
729  }
730 
731  auto swap(cond_ptr& other) -> void {
732  std::swap(ptr_, other.ptr_);
733  std::swap(owns_, other.owns_);
734  std::swap(get_deleter(), other.get_deleter());
735  }
736 
737  KBLIB_NODISCARD auto get() & noexcept -> T* { return ptr_; }
738 
739  KBLIB_NODISCARD auto get() const& noexcept -> const T* { return ptr_; }
740 
741  explicit operator bool() const noexcept { return ptr_; }
742 
743  KBLIB_NODISCARD T& operator[](std::size_t index) & noexcept {
744  return ptr_[index];
745  }
746 
747  KBLIB_NODISCARD const T& operator[](std::size_t index) const& noexcept {
748  return ptr_[index];
749  }
750 
751  KBLIB_NODISCARD friend constexpr auto operator==(
752  const cond_ptr& lhs, const cond_ptr& rhs) noexcept -> bool {
753  return lhs.ptr_ == rhs.ptr_;
754  }
755 
756  KBLIB_NODISCARD friend constexpr auto operator==(
757  const unique& lhs, const cond_ptr& rhs) noexcept -> bool {
758  return lhs.get() == rhs.ptr_;
759  }
760 
761  KBLIB_NODISCARD friend constexpr auto operator==(const cond_ptr& lhs,
762  const unique& rhs) noexcept
763  -> bool {
764  return lhs.ptr_ == rhs.get();
765  }
766 
767  private:
768  T* ptr_ = nullptr;
769  bool owns_ = false;
770 };
771 
772 template <typename T, typename Deleter>
773 KBLIB_NODISCARD auto make_cond_ptr(std::unique_ptr<T, Deleter>&& arg) noexcept
775  return cond_ptr<T>(std::move(arg));
776 }
777 
778 template <typename T>
779 KBLIB_NODISCARD auto make_cond_ptr(T* arg, bool owner = false) noexcept
780  -> cond_ptr<T> {
781  return cond_ptr<T>(arg, owner);
782 }
783 
784 template <typename T, typename Deleter>
785 KBLIB_NODISCARD auto make_cond_ptr(T* arg, Deleter del) noexcept
787  return cond_ptr<T, Deleter>(arg, del);
788 }
789 
790 template <typename T, typename Deleter>
791 KBLIB_NODISCARD auto make_cond_ptr(T* arg, bool owner, Deleter del) noexcept
793  return cond_ptr<T, Deleter>(arg, owner, del);
794 }
795 
796 } // namespace kblib
797 
798 #endif // MEMORY_H
Provides general-purpose algorithms, similar to the <algorithms> header.
cond_ptr(cond_ptr &&other) noexcept
Definition: memory.h:632
auto get_deleter() const noexcept -> const Deleter &
Definition: memory.h:709
auto release() &noexcept -> T *
Definition: memory.h:702
static auto adopt(T *p, deleter_type del) noexcept -> cond_ptr
Definition: memory.h:640
auto operator=(unique &&rhs) -> cond_ptr &
Definition: memory.h:662
auto swap(cond_ptr &other) -> void
Definition: memory.h:731
cond_ptr(T *p, std::decay_t< Deleter > del) noexcept
Definition: memory.h:620
detail_memory::filter_deleter_pointer_t< Deleter, T > pointer
Definition: memory.h:601
auto get_deleter() noexcept -> Deleter &
Definition: memory.h:707
auto operator=(cond_ptr &&rhs) &noexcept -> cond_ptr &
Definition: memory.h:654
T & operator[](std::size_t index) &noexcept
Definition: memory.h:743
cond_ptr(unique &&p) noexcept
Definition: memory.h:624
std::unique_ptr< T[], Deleter > unique
Definition: memory.h:610
const T & operator[](std::size_t index) const &noexcept
Definition: memory.h:747
auto get() &noexcept -> T *
Definition: memory.h:737
auto to_unique() &&noexcept -> unique
Transfers ownership to a unique_ptr if possible. If *this is not owning, returns nullptr.
Definition: memory.h:679
auto reset(T *p=nullptr, bool owner=false, std::decay_t< Deleter > del={}) &noexcept -> void
Definition: memory.h:713
constexpr friend auto operator==(const unique &lhs, const cond_ptr &rhs) noexcept -> bool
Definition: memory.h:756
auto weak() const &noexcept -> cond_ptr
Definition: memory.h:697
constexpr friend auto operator==(const cond_ptr &lhs, const unique &rhs) noexcept -> bool
Definition: memory.h:761
static auto adopt(T *p) noexcept -> cond_ptr
Definition: memory.h:637
auto reset(T *p, std::decay_t< Deleter > del={}) &noexcept -> void
Definition: memory.h:722
constexpr friend auto operator==(const cond_ptr &lhs, const cond_ptr &rhs) noexcept -> bool
Definition: memory.h:751
auto get() const &noexcept -> const T *
Definition: memory.h:739
cond_ptr(const cond_ptr &other)=delete
cond_ptr(T *p, bool owner=false, std::decay_t< Deleter > del={}) noexcept
Definition: memory.h:615
auto owns() const noexcept -> bool
Definition: memory.h:701
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:455
auto reset(T *p=nullptr, bool owner=false, std::decay_t< Deleter > del={}) &noexcept -> void
Definition: memory.h:531
auto operator*() const &noexcept -> const T &
Definition: memory.h:565
auto operator->() &noexcept -> T *
Definition: memory.h:569
auto operator*() &noexcept -> T &
Definition: memory.h:563
auto release() &noexcept -> T *
Definition: memory.h:518
std::unique_ptr< T, Deleter > unique
Definition: memory.h:425
auto owns() const noexcept -> bool
Definition: memory.h:517
cond_ptr(T *p, bool owner=false, std::decay_t< Deleter > del={}) noexcept
Definition: memory.h:430
~cond_ptr() noexcept
Definition: memory.h:507
auto swap(cond_ptr &other) noexcept(fakestd::is_nothrow_swappable< Deleter >::value) -> void
Definition: memory.h:549
cond_ptr(T *p, std::decay_t< Deleter > del) noexcept
Definition: memory.h:435
auto get() &noexcept -> T *
Definition: memory.h:557
Deleter deleter_type
Definition: memory.h:418
cond_ptr(const cond_ptr &other)=delete
auto get_deleter() noexcept -> Deleter &
Definition: memory.h:523
auto operator=(unique &&rhs) -> cond_ptr &
Definition: memory.h:478
auto operator=(cond_ptr &&rhs) &noexcept -> cond_ptr &
Definition: memory.h:469
auto get_deleter() const noexcept -> const Deleter &
Definition: memory.h:527
cond_ptr(unique &&p) noexcept
Definition: memory.h:439
auto get() const &noexcept -> const T *
Definition: memory.h:559
cond_ptr() noexcept=default
constexpr friend auto operator==(const unique &lhs, const cond_ptr &rhs) noexcept -> bool
Definition: memory.h:580
auto to_unique() &&noexcept -> unique
Transfers ownership to a unique_ptr if possible. If *this is not owning, returns nullptr.
Definition: memory.h:495
static auto adopt(T *p) noexcept -> cond_ptr
Definition: memory.h:452
auto operator->() const &noexcept -> const T *
Definition: memory.h:571
constexpr friend auto operator==(const cond_ptr &lhs, const unique &rhs) noexcept -> bool
Definition: memory.h:585
constexpr friend auto operator==(const cond_ptr &lhs, const cond_ptr &rhs) noexcept -> bool
Definition: memory.h:575
auto weak() const &noexcept -> cond_ptr
Definition: memory.h:513
detail_memory::filter_deleter_pointer_t< Deleter, T > pointer
Definition: memory.h:416
auto reset(T *p, std::decay_t< Deleter > del={}) &noexcept -> void
Definition: memory.h:540
cond_ptr(cond_ptr &&other) noexcept
Definition: memory.h:447
auto operator=(const live_ptr< mT > &o) -> live_ptr &
Definition: memory.h:367
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:360
live_ptr(live_ptr< mT > &&o) noexcept
Definition: memory.h:363
live_ptr(const live_wrapper< mT > &o)
Definition: memory.h:378
auto operator=(live_ptr< mT > &&o) noexcept -> live_ptr &
Definition: memory.h:372
live_ptr(live_ptr< T > &&o) noexcept=default
auto operator=(const live_wrapper< mT > &o) -> live_ptr &
Definition: memory.h:382
auto operator=(live_ptr &&o) noexcept -> live_ptr &=default
~live_ptr()=default
auto operator=(live_wrapper< T > &o) -> live_ptr &
Definition: memory.h:337
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:333
live_ptr< T > ref()
Definition: memory.h:393
live_ptr< const T > cref() const
Definition: memory.h:403
live_ptr< const T > ref() const
Definition: memory.h:398
null_construct< detail_memory::on_destroy< std::vector< live_wrapper ** >, _destroy > > _observers
Definition: memory.h:205
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:178
The main namespace in which all entities from kblib are defined.
Definition: algorithm.h:44
constexpr auto exchange(T &obj, U &&new_value) -> T
Definition: fakestd.h:718
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:130
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(std::unique_ptr< T, Deleter > &&arg) noexcept -> cond_ptr< T, Deleter >
Definition: memory.h:773
Definition: bits.h:714
auto base() const noexcept -> const T &
Definition: memory.h:95
auto base() const noexcept -> const T &
Definition: memory.h:103
auto base() const noexcept -> const T &
Definition: memory.h:129
typename std::remove_reference< D >::type::pointer type
Definition: memory.h:79
auto operator->() const noexcept -> const T *
Definition: memory.h:231
friend auto operator==(const T *lhs, const D &rhs) -> bool
Definition: memory.h:253
auto operator->() noexcept -> T *
Definition: memory.h:230
friend auto operator==(const D &lhs, const D &rhs) -> bool
Definition: memory.h:242
live_ptr_base(const live_ptr_base &o)
Definition: memory.h:278
auto operator=(D &&o) noexcept -> D &
Definition: memory.h:291
friend auto operator==(std::nullptr_t, const D &rhs) -> bool
Definition: memory.h:238
auto operator=(live_ptr_base &&o) noexcept -> live_ptr_base &
Definition: memory.h:272
auto operator*() const noexcept -> const T &
Definition: memory.h:228
auto operator=(const live_ptr_base &o) noexcept -> live_ptr_base &
Definition: memory.h:266
auto operator=(const D &o) -> D &
Definition: memory.h:285
friend auto operator==(const D &lhs, const T *rhs) -> bool
Definition: memory.h:246
live_wrapper< mT > * obj
Definition: memory.h:310
friend auto operator==(const D &lhs, std::nullptr_t) -> bool
Definition: memory.h:235
auto operator*() noexcept -> T &
Definition: memory.h:227
live_ptr_base(live_ptr_base &&o) noexcept
Definition: memory.h:282
auto operator()() const noexcept -> void
Definition: memory.h:136
rule_zero(Args &&... args)
Definition: memory.h:143
auto operator()(std::vector< live_wrapper ** > &&self) const noexcept -> void
Definition: memory.h:193
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_NODISCARD
This internal macro is used to provide a fallback for [[nodiscard]] in C++14.
Definition: tdecl.h:81