C++ Library Extensions 2022.12.09
To help learn modern C++ programming
03-unique_ptr.cpp
Go to the documentation of this file.
1#include <tpf_output.hpp>
2
5
6class DummyClass
7{
8 public:
9 enum class Operation: int { as_const_lvalue_ref, as_lvalue_ref, as_move };
10
11 private:
12 std::unique_ptr<int> m_member;
13
14 public:
15 DummyClass(int value=0):
16 m_member{ std::make_unique<int>(value) } { }
17
18 // we have to break the tie between member function get_member
19 // with its enclosing class, DummyClass. How?
20
21 // now we have broken the tie between DummyClass and get_member()
22 template<auto Opr = Operation::as_const_lvalue_ref>
23 decltype(auto) get_member()
24 {
25 // this is default return type
26 if constexpr(Opr == Operation::as_const_lvalue_ref)
27 {
28 return static_cast<const std::unique_ptr<int>& >(this->m_member);
29 }
30 else if constexpr(Opr == Operation::as_lvalue_ref)
31 {
32 return static_cast< std::unique_ptr<int>&>(this->m_member);
33 }
34 else
35 {
36 // after this, this->m_member is invalid or valid
37 // depending on its caller
38 return std::move(this->m_member);
39 }
40 }
41};
42
44{
45 DummyClass dummy{ 10 };
46
47 constexpr auto const_lvalue_ref = DummyClass::Operation::as_const_lvalue_ref;
48 constexpr auto lvalue_ref = DummyClass::Operation::as_lvalue_ref;
49 constexpr auto as_move = DummyClass::Operation::as_move;
50
51 decltype(auto) p1 = dummy.get_member();
52
53 stream << "The type of p1: " << Tpf_GetTypeCategory(p1)
54 <<"\nits value is " << *p1 << endl;
55
56 decltype(auto) p2 = dummy.get_member<lvalue_ref>();
57
58 stream << "The type of p2: " << Tpf_GetTypeCategory(p2)
59 <<"\nits value is " << *p2 << endl;
60
61 // at this point, we move dummy.m_member
62 // to p3. After this call dummy.m_member is invalid
63 auto p3 = dummy.get_member<as_move>();
64
65 stream << "The type of p3: " << Tpf_GetTypeCategory(p3)
66 <<"\nits value is " << *p3 << endl;
67
68 // at this point, p3 now has the ownership of the memory
69 // that was previously owned by dummy.
70
71 // WARNING: Since we move the ownership of dummy.m_member
72 // to p3, now p1 and p2 are invalid.
73
74 if(p1)
75 {
76 stream <<"p1 is valid " << *p1 << endl;
77 }
78 else
79 {
80 stream << "p1 is invalid" << endl;
81 }
82
83 if(p2)
84 {
85 stream <<"p2 is valid " << *p2 << endl;
86 }
87 else
88 {
89 stream << "p2 is invalid" << endl;
90 }
91
92 // p4 is now raw pointer of type int*
93 auto p4 = p3.release();
94
95 if(p1)
96 {
97 stream <<"p1 is valid " << *p1 << endl;
98 }
99 else
100 {
101 stream << "p1 is invalid" << endl;
102 }
103
104 if(p2)
105 {
106 stream <<"p2 is valid " << *p2 << endl;
107 }
108 else
109 {
110 stream << "p2 is invalid" << endl;
111 }
112
113 // restore p2 with p4, the raw pointer of type int*
114 p2.reset(p4);
115
116 if(p1)
117 {
118 stream <<"p1 is valid " << *p1 << endl;
119 }
120 else
121 {
122 stream << "p1 is invalid" << endl;
123 }
124
125 if(p2)
126 {
127 stream <<"p2 is valid " << *p2 << endl;
128 }
129 else
130 {
131 stream << "p2 is invalid" << endl;
132 }
133
134}
135
136int main()
137{
139}
tpf::sstream stream
void test_advanced_return_type()
auto endl
int main()
decltype(auto) get_member()
DummyClass(int value=0)
constexpr auto endl
Definition: tpf_output.hpp:973
Stream output operators << are implemented.
#define Tpf_GetTypeCategory(instance_arg)
A macro that returns instance_arg's type category string name.
Definition: tpf_types.hpp:1428