opynsim
Unofficial C++ Documentation
Loading...
Searching...
No Matches
clone_ptr.h
Go to the documentation of this file.
1#pragma once
2
3#include <concepts>
4#include <iosfwd>
5#include <memory>
6#include <type_traits>
7#include <utility>
8
9namespace osc
10{
11 // `ClonePtr` is a smart pointer that owns and manages another object through
12 // a pointer and disposes of that object when `ClonePtr` goes out of scope.
13 //
14 // This is essentially the same as how `std::unique_ptr` works. The main difference
15 // that `ClonePtr` offers is that it is copyable. Copying is achieved by calling a
16 // cloning function when necessary.
17 template<typename T, typename Deleter = std::default_delete<T>>
19 public:
20 using pointer = T*;
21 using element_type = T;
23
24 // constructs a `ClonePtr` that owns nothing
25 constexpr ClonePtr() noexcept : value_{nullptr} {}
26
27 // constructs a `ClonePtr` that owns nothing
28 constexpr ClonePtr(std::nullptr_t) noexcept : value_{nullptr} {}
29
30 // constructs a `ClonePtr` that owns `p`
31 explicit ClonePtr(pointer p) noexcept : value_{p} {}
32
33 // constructs a `ClonePtr` that owns `p`
34 explicit ClonePtr(std::unique_ptr<element_type, deleter_type> p) noexcept : value_{std::move(p)} {}
35
36 // constructs a `ClonePtr` by `clone`ing `src`
37 ClonePtr(const ClonePtr& src) : value_{src.value_ ? src.value_->clone() : nullptr} {}
38
39 // constructs `ClonePtr` by transferring ownership from a rvalue
41
42 // constructs `ClonePtr` by transferring ownership from a rvalue (with conversion)
46 (not std::is_array_v<U>) and
48 ClonePtr(ClonePtr<U, E>&& tmp) noexcept : value_{std::move(tmp.value_)} {}
49
50 // if `get() == nullptr` there are no effects. Otherwise, the owned object is destroyed via `get_deleter()(get())`
52
53 // if `rhs.get() != nullptr`, assigns `rhs.clone()` to `this`; otherwise, `reset`s `this`
55 {
56 if (&rhs == this) {
57 }
58 else if (rhs.get()) {
59 value_ = std::unique_ptr<element_type>{rhs.value_->clone()};
60 }
61 else {
62 reset();
63 }
64 return *this;
65 }
66
68
70 {
71 *this = ClonePtr{std::move(ptr)};
72 return *this;
73 }
74
75 template<typename U, typename E>
76 requires
77 (not std::is_array_v<U>) and
78 std::convertible_to<typename ClonePtr<U, E>::element_type, element_type> and
79 std::is_assignable_v<Deleter&, E&&>
80 ClonePtr& operator=(ClonePtr<U, E>&& rhs) noexcept
81 {
82 value_ = std::move(rhs.value_);
83 return *this;
84 }
85
86 ClonePtr& operator=(std::nullptr_t) noexcept
87 {
88 reset();
89 return *this;
90 }
91
93 {
94 return value_.release();
95 }
96
98 {
99 value_.reset(ptr);
100 }
101
102 void swap(ClonePtr& other) noexcept
103 {
104 value_.swap(other.value_);
105 }
106
108 {
109 return value_.get();
110 }
111
113 {
114 return value_.get_deleter();
115 }
116
118 {
119 return value_.get_deleter();
120 }
121
122 explicit operator bool() const noexcept
123 {
124 return value_;
125 }
126
127 std::add_lvalue_reference_t<T> operator*() const noexcept(noexcept(*std::declval<pointer>()))
128 {
129 return *value_;
130 }
131
133 {
134 return value_.get();
135 }
136
137 friend void swap(ClonePtr& lhs, ClonePtr& rhs) noexcept
138 {
139 lhs.swap(rhs);
140 }
141
142 template<typename T2, typename D2>
143 friend bool operator==(const ClonePtr& lhs, const ClonePtr<T2, D2>& rhs)
144 {
145 return lhs.get() == rhs.get();
146 }
147
148 template<typename CharT, typename Traits>
149 friend std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, const ClonePtr& p)
150 {
151 return os << p.get();
152 }
153
154 private:
155 template<typename, typename> friend class ClonePtr;
156
157 std::unique_ptr<T, Deleter> value_;
158 };
159
160 // constructs an object of type `T` and wraps it in a `ClonePtr`
161 template<typename T, typename... Args>
162 requires std::constructible_from<T, Args&&...>
164 {
165 return ClonePtr<T>{std::make_unique<T>(std::forward<Args>(args)...)};
166 }
167}
168
169template<typename T, typename Deleter>
170struct std::hash<osc::ClonePtr<T, Deleter>> final {
171 size_t operator()(const osc::ClonePtr<T, Deleter>& p) const noexcept
172 {
173 return std::hash(p.get());
174 }
175};
Definition clone_ptr.h:18
pointer release() noexcept
Definition clone_ptr.h:92
friend std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const ClonePtr &p)
Definition clone_ptr.h:149
void reset(pointer ptr=pointer()) noexcept
Definition clone_ptr.h:97
const Deleter & get_deleter() const noexcept
Definition clone_ptr.h:117
Deleter & get_deleter() noexcept
Definition clone_ptr.h:112
ClonePtr(pointer p) noexcept
Definition clone_ptr.h:31
pointer get() const noexcept
Definition clone_ptr.h:107
friend void swap(ClonePtr &lhs, ClonePtr &rhs) noexcept
Definition clone_ptr.h:137
std::add_lvalue_reference_t< T > operator*() const noexcept(noexcept(*std::declval< pointer >()))
Definition clone_ptr.h:127
constexpr ClonePtr(std::nullptr_t) noexcept
Definition clone_ptr.h:28
pointer operator->() const noexcept
Definition clone_ptr.h:132
T * pointer
Definition clone_ptr.h:20
ClonePtr & operator=(ClonePtr &&) noexcept=default
ClonePtr(std::unique_ptr< element_type, deleter_type > p) noexcept
Definition clone_ptr.h:34
ClonePtr(const ClonePtr &src)
Definition clone_ptr.h:37
constexpr ClonePtr() noexcept
Definition clone_ptr.h:25
T element_type
Definition clone_ptr.h:21
friend bool operator==(const ClonePtr &lhs, const ClonePtr< T2, D2 > &rhs)
Definition clone_ptr.h:143
ClonePtr(ClonePtr &&) noexcept=default
Deleter deleter_type
Definition clone_ptr.h:22
ClonePtr & operator=(std::nullptr_t) noexcept
Definition clone_ptr.h:86
void swap(ClonePtr &other) noexcept
Definition clone_ptr.h:102
~ClonePtr() noexcept=default
Definition custom_decoration_generator.h:5
constexpr U to(T &&value)
Definition conversion.h:56
ClonePtr< T > make_cloneable(Args &&... args)
Definition clone_ptr.h:163
and
Definition algorithms.h:158
size_t operator()(const osc::ClonePtr< T, Deleter > &p) const noexcept
Definition clone_ptr.h:171