C++ Library Extensions 2022.12.09
To help learn modern C++ programming
06-unique_ptr.cpp
Go to the documentation of this file.
1#include <tpf_output.hpp>
2
5
6// #include <iostream>
7// #include <memory> // for unique_ptr and shared_ptr
8
9// auto& stream = std::cout;
10// auto endl = "\n";
11
12// template<typename Type_1, typename Type_2>
13// std::ostream& operator << (std::ostream& os, const std::unique_ptr<Type_1, Type_2>& ptr)
14// {
15// if(ptr)
16// os << *ptr;
17
18// return os;
19// }
20
21// template<typename Type>
22// std::ostream& operator << (std::ostream& os, const std::shared_ptr<Type>& ptr)
23// {
24// if(ptr)
25// os << *ptr;
26
27// return os;
28// }
29
31{
32 auto uptr = std::make_unique<int>(10);
33
34 auto sptr = std::make_shared<int>(100);
35
36 if (uptr)
37 stream <<"*uptr = " << uptr << endl;
38
39 if(sptr)
40 stream <<"*sptr = " << sptr << endl;
41
42}
43
45{
46 using element_t = std::tuple<int, std::string>;
47
48 using uptr_t = std::unique_ptr<element_t>;
49 using container_t = std::vector<uptr_t>;
50
51 size_t size = 10;
52
53 container_t uptr_container; uptr_container.reserve(size);
54
55 for(size_t i = 0; i < size; ++i)
56 {
57 tpf::sstream os;
58 os << "Good Man + " << i ;
59
60 auto t = element_t{(int)i, os.str() };
61 uptr_container.emplace_back( std::make_unique<element_t>( std::move(t) ) );
62 }
63
64 stream << uptr_container << endl;
65}
66
68{
69 auto uptr = std::make_unique<int>(10);
70
71 stream << "uptr = " << uptr << endl;
72
73 auto sptr = std::shared_ptr<int>( uptr.release() );
74
75 stream << "sptr = " << sptr << endl;
76
77 if(uptr)
78 {
79 stream << "Uptr is still valid... it's wrong " << endl;
80 }
81 else
82 {
83 stream << "Now uptr is invalid" << endl;
84 }
85
86 /*
87 * How can we convert shared_ptr to unique_ptr?
88 *
89 * The short answer is IMPOSSIBLE!
90 *
91 * The long answer is STILL IMPOSSIBLE!
92 *
93 * At best, we can recreate (or clone)
94 * shared_ptr to unique_ptr
95 * */
96
97 if(sptr.use_count()==1) // not sharing the pointer with other shared_ptr
98 {
99 // basically, we are creating a new instance of unique_ptr
100 // using the value of the object that the shared_pter owns.
101 uptr = std::make_unique<int>( *sptr );
102 sptr = nullptr;
103 }
104
105 if(uptr)
106 {
107 stream << "Now uptr is reconstructed: " << uptr << endl;
108 }
109 else
110 {
111 stream << "uptr is still invalid" << endl;
112 }
113
114 if(sptr)
115 {
116 stream << "Wow, sptr is still valid: " << sptr << endl;
117 }
118 else
119 {
120 stream << "Of course, sptr should be invalid" << endl;
121 }
122
123}
124
125template<typename ElementType>
127{
128 public:
129 using uptr_t = std::unique_ptr<ElementType>;
130 using sptr_t = std::shared_ptr<ElementType>;
131 using usptr_t = std::variant<uptr_t, sptr_t>;
132
133 private:
134 usptr_t m_ptr;
135
136 public:
137 smarter_ptr(ElementType value = ElementType{}):
138 m_ptr { std::make_unique<ElementType>(value) } { }
139
140 // do not privde copy constructor
141 smarter_ptr(const smarter_ptr&) = delete;
143
144 smarter_ptr(smarter_ptr&& rhs): m_ptr{ std::move(rhs.m_ptr) } { }
145
147 {
148 if(this != std::addressof(rhs))
149 {
150 this->m_ptr = std::move(rhs.m_ptr);
151
152 }
153
154 return *this;
155 }
156
158 {
159 if(auto ptr = std::get_if<uptr_t>(&this->m_ptr))
160 return true;
161 else
162 return false;
163 }
164
166 {
167 if(auto ptr = std::get_if<sptr_t>(&this->m_ptr))
168 return true;
169 else
170 return false;
171 }
172
173 ElementType* get()
174 {
175 if(auto uptr = std::get_if<uptr_t>(&this->m_ptr))
176 return uptr->get();
177 else if(auto sptr = std::get_if<sptr_t>(&this->m_ptr))
178 return sptr->get();
179 else
180 return nullptr;
181 }
182
183 smarter_ptr& operator = (ElementType value)
184 {
185 if(auto uptr = std::get_if<uptr_t>(&this->m_ptr))
186 {
187 // stream << "type of *uptr: " << Tpf_GetTypeCategory(*uptr) << endl;
188
189 **uptr = value;
190 return *this;
191 }
192 else if(auto sptr = std::get_if<sptr_t>(&this->m_ptr))
193 {
194 // stream << "type of *sptr: " << Tpf_GetTypeCategory(*sptr) << endl;
195
196 **sptr = value;
197 return *this;
198 }
199 else
200 return *this;
201 }
202
204 {
205 if(auto sptr = std::get_if<sptr_t>(&this->m_ptr))
206 return *this;
207 else if(auto uptr = std::get_if<uptr_t>(&this->m_ptr))
208 {
209 // converting from uptr_t to sptr_t
210 this->m_ptr = sptr_t(uptr->release());
211 return *this;
212 }
213 else
214 return *this;
215 }
216
218 {
219 if(auto uptr = std::get_if<uptr_t>(&this->m_ptr))
220 return *this;
221 else if(auto sptr = std::get_if<sptr_t>(&this->m_ptr))
222 {
223 // sptr is pointer to shared_ptr
224 // *sptr is type of shared_ptr
225 // **sptr is the value the shared_ptr owns
226 auto uptr = std::make_unique<ElementType>(**sptr);
227 *sptr = nullptr;
228
229 this->m_ptr = std::move(uptr);
230
231 return *this;
232 }
233 else
234 return *this;
235 }
236
238 {
239 os << sp.m_ptr;
240 return os;
241 }
242};
243
245{
246 smarter_ptr<int> sp{10};
247
248 stream << "sp = " << sp << endl;
249
250 stream <<"sp.is_unique_ptr()? " << sp.is_unique_ptr() << endl;
251
252 sp.to_shared_ptr(); // convert uptr to shared ptr
253
254 stream << "sp.is_shared_ptr()? " << sp.is_shared_ptr() << endl;
255
256 stream << "sp.is_unique_ptr()? " << sp.is_unique_ptr() << endl;
257
258 if(sp.is_shared_ptr())
259 {
260 stream << "Now, shared_ptr " << sp << endl;
261 }
262 else
263 {
264 stream << "Still not shared ptr " << endl;
265 }
266
267 sp = 30;
268
269 stream << "The value of sp now ? " << sp << endl;
270
271 sp.to_unique_ptr();
272
273 stream <<"Restored back from shared_ptr: " << sp << endl;
274}
275
276int main()
277{
278 // test_unique_ptr_and_shared_ptr_output();
279
280 // why_operator_overloading_for_unique_ptr_and_shared_ptr();
281
282 // test_convert_unique_ptr_to_shared_ptr();
283
285}
286
void why_operator_overloading_for_unique_ptr_and_shared_ptr()
tpf::sstream stream
void test_unique_ptr_and_shared_ptr_output()
void test_smarter_ptr()
auto endl
int main()
void test_convert_unique_ptr_to_shared_ptr()
smarter_ptr & to_unique_ptr()
bool is_shared_ptr()
smarter_ptr & operator=(smarter_ptr &&rhs)
std::unique_ptr< ElementType > uptr_t
std::variant< uptr_t, sptr_t > usptr_t
bool is_unique_ptr()
smarter_ptr(const smarter_ptr &)=delete
smarter_ptr(smarter_ptr &&rhs)
smarter_ptr & operator=(const smarter_ptr &)=delete
friend tpf::sstream & operator<<(tpf::sstream &os, const smarter_ptr &sp)
ElementType * get()
std::shared_ptr< ElementType > sptr_t
smarter_ptr(ElementType value=ElementType{})
smarter_ptr & to_shared_ptr()
std::string str() const
Definition: tpf_output.hpp:951
constexpr auto endl
Definition: tpf_output.hpp:973
Stream output operators << are implemented.