1 // This is mul/mbl/mbl_cloneable_ptr.h
2 #ifndef mbl_cloneable_ptr_h
3 #define mbl_cloneable_ptr_h
4 //:
5 // \file
6
7 #include <vsl/vsl_binary_loader.h>
8 #include <cassert>
9 #ifdef _MSC_VER
10 # include <vcl_msvc_warnings.h>
11 #endif
12
13 //=======================================================================
14 //: Cunning pointer for objects that can be cloned.
15 // Used to record base class pointers to objects
16 // When copied, the object pointed to gets cloned.
17 // When written or read to/from binary streams,
18 // suitable polymorphic I/O is invoked.
19 //
20 // \code
21 // std::unique_ptr<T> inst = get_from_some_factory_function();
22 // mbl_cloneable_ptr<T> long_term_store;
23 // long_term_store = inst.release();
24 // \endcode
25 template <class BaseClass>
26 class mbl_cloneable_ptr
27 {
28 BaseClass* ptr_;
29 public:
30 //: Default constructor (zeros pointer)
mbl_cloneable_ptr()31 mbl_cloneable_ptr() : ptr_(nullptr) {}
32
33 //: Delete object pointed to and set pointer to zero
deleteObject()34 void deleteObject() { delete ptr_; ptr_=nullptr; }
35
36 //: Destructor
~mbl_cloneable_ptr()37 ~mbl_cloneable_ptr() { deleteObject(); }
38
39 //: Copy constructor
mbl_cloneable_ptr(const mbl_cloneable_ptr<BaseClass> & p)40 mbl_cloneable_ptr(const mbl_cloneable_ptr<BaseClass>& p) : ptr_(nullptr) { *this = p; }
41
42 //: Construct from pointer, making a clone of r.
mbl_cloneable_ptr(const BaseClass & r)43 mbl_cloneable_ptr(const BaseClass& r) : ptr_(r.clone()) { assert(ptr_); }
44
45 //: Constructor from pointer, taking ownership of *p.
mbl_cloneable_ptr(BaseClass * p)46 mbl_cloneable_ptr(BaseClass* p) : ptr_(p) { assert(ptr_); }
47
48 //: Copy operator
49 mbl_cloneable_ptr<BaseClass>& operator=(const mbl_cloneable_ptr<BaseClass>& p)
50 {
51 if (this==&p) return *this;
52 deleteObject(); if (p.ptr_!=nullptr) ptr_=p.ptr_->clone();
53 return *this;
54 }
55
56 //: Copy operator - takes clone of p
57 mbl_cloneable_ptr<BaseClass>& operator=(const BaseClass& p)
58 {
59 if (ptr_==&p) return *this;
60 deleteObject();
61 ptr_= p.clone();
62 return *this;
63 }
64
65 //: Copy operator - takes responsibility for *p
66 // Sets internal pointer to p, and takes responsibility
67 // for deleting *p
68 mbl_cloneable_ptr<BaseClass>& operator=(BaseClass* p)
69 {
70 if (ptr_==p) return *this;
71 deleteObject();
72 ptr_= p;
73 return *this;
74 }
75
76 //: Return true if pointer defined
isDefined()77 bool isDefined() const { return ptr_!=nullptr; }
78
79 //: Make object behave like pointer to BaseClass
80 const BaseClass* operator->() const { return ptr_; }
81
82 //: Make object behave like pointer to BaseClass
83 BaseClass* operator->() { return ptr_; }
84
85 //: Return actual pointer
ptr()86 const BaseClass* ptr() const { return ptr_; }
87
88 //: Return actual pointer
ptr()89 BaseClass* ptr() { return ptr_; }
90
91 //: Return wrapped pointer and give up ownership
release()92 BaseClass* release()
93 { BaseClass* p = ptr_; ptr_=nullptr; return p; }
94
95 //: Cast to allow object to look like thing pointed to
96 operator BaseClass&() { assert(ptr_!=nullptr); return *ptr_; }
97
98 //: Dereferencing the pointer
99 BaseClass &operator * () { return *ptr_; }
100
101 //: Dereferencing the pointer
102 const BaseClass &operator * () const { return *ptr_; }
103
104 //: Cast to allow object to look like thing pointed to
105 operator const BaseClass&() const { assert(ptr_!=nullptr); return *ptr_; }
106
107 //: Save to binary stream
b_write(vsl_b_ostream & bfs)108 void b_write(vsl_b_ostream& bfs) const
109 {
110 vsl_b_write(bfs,ptr_);
111 }
112
113 //: Load from binary stream
b_read(vsl_b_istream & bfs)114 void b_read(vsl_b_istream& bfs)
115 {
116 deleteObject();
117 vsl_b_read(bfs,ptr_);
118 }
119 };
120
121 template <class BaseClass>
vsl_b_write(vsl_b_ostream & bfs,const mbl_cloneable_ptr<BaseClass> & p)122 void vsl_b_write(vsl_b_ostream& bfs, const mbl_cloneable_ptr<BaseClass>& p)
123 { p.b_write(bfs); }
124
125 template <class BaseClass>
vsl_b_read(vsl_b_istream & bfs,mbl_cloneable_ptr<BaseClass> & p)126 void vsl_b_read(vsl_b_istream& bfs, mbl_cloneable_ptr<BaseClass>& p)
127 { p.b_read(bfs); }
128
129
130 //=======================================================================
131 //: Cunning non-zero pointer for objects that can be cloned.
132 // The pointer is guaranteed to always point to something.
133 // Used to record base class pointers to objects
134 // When copied, the object pointed to gets cloned.
135 // When written or read to/from binary streams,
136 // suitable polymorphic I/O is invoked.
137 //
138 // To take ownership of the contents of a std::unique_ptr<T> use
139 // \code
140 // std::unique_ptr<T> inst = get_from_some_factory_function();
141 // mbl_cloneable_nzptr<T> long_term_store(inst.release());
142 // \endcode
143 template <class BaseClass>
144 class mbl_cloneable_nzptr
145 {
146 BaseClass* ptr_;
147 public:
148
149 //: Destructor
~mbl_cloneable_nzptr()150 ~mbl_cloneable_nzptr() { delete ptr_; }
151
152 //: Copy constructor
153 // There is no default constructor.
mbl_cloneable_nzptr(const mbl_cloneable_nzptr<BaseClass> & cp)154 mbl_cloneable_nzptr(const mbl_cloneable_nzptr<BaseClass>& cp):
155 ptr_(cp.ptr_->clone()) { assert(ptr_); }
156
157 //: Construct from pointer, making a clone of r.
158 // There is no default constructor.
mbl_cloneable_nzptr(const BaseClass & r)159 mbl_cloneable_nzptr(const BaseClass& r) : ptr_(r.clone()) { assert(ptr_); }
160
161 //: Constructor from pointer, taking ownership of *p.
162 // There is no default constructor.
mbl_cloneable_nzptr(BaseClass * p)163 mbl_cloneable_nzptr(BaseClass* p) : ptr_(p) { assert(ptr_); }
164
165 //: Copy operator
166 mbl_cloneable_nzptr<BaseClass>& operator=(const mbl_cloneable_nzptr<BaseClass>& cp)
167 {
168 if (this==&cp) return *this;
169 BaseClass * tmp=cp.ptr_->clone();
170 assert(tmp);
171 delete ptr_;
172 ptr_ = tmp;
173 return *this;
174 }
175
176 //: Copy operator - takes clone of r
177 mbl_cloneable_nzptr<BaseClass>& operator=(const BaseClass& r)
178 {
179 if (ptr_==&r) return *this;
180 BaseClass * tmp=r.clone(); // Do it in this order, in case clone throws an exception.
181 assert(tmp);
182 delete ptr_;
183 ptr_= tmp;
184 return *this;
185 }
186
187 //: Copy operator - takes responsibility for *p
188 // Sets internal pointer to p, and takes responsibility
189 // for deleting *p
190 mbl_cloneable_nzptr<BaseClass>& operator=(BaseClass* p)
191 {
192 assert(p);
193 if (ptr_==p) return *this;
194 delete ptr_;
195 ptr_= p;
196 return *this;
197 }
198
199 //: Return true.
isDefined()200 bool isDefined() const { return true; }
201
202 //: Make object behave like pointer to BaseClass
203 const BaseClass* operator->() const { return ptr_; }
204
205 //: Make object behave like pointer to BaseClass
206 BaseClass* operator->() { return ptr_; }
207
208 //: Return actual pointer
ptr()209 const BaseClass* ptr() const { return ptr_; }
210
211 //: Return actual pointer
ptr()212 BaseClass* ptr() { return ptr_; }
213
214 //: Return and give up ownership of wrapped pointer, while taking ownership a new pointer.
replace(BaseClass * p)215 BaseClass* replace(BaseClass* p)
216 { BaseClass* old = ptr_; ptr_=p; return old; }
217
218 //: Cast to allow object to look like thing pointed to
219 operator BaseClass&() { return *ptr_; }
220
221 //: Cast to allow object to look like thing pointed to
222 operator const BaseClass&() const { return *ptr_; }
223
224 //: Dereferencing the pointer
225 BaseClass &operator * () { return *ptr_; }
226
227 //: Dereferencing the pointer
228 const BaseClass &operator * () const { return *ptr_; }
229
230 //: Save to binary stream
b_write(vsl_b_ostream & bfs)231 void b_write(vsl_b_ostream& bfs) const
232 {
233 vsl_b_write(bfs,ptr_);
234 }
235
236 //: Load from binary stream
b_read(vsl_b_istream & bfs)237 void b_read(vsl_b_istream& bfs)
238 {
239 delete ptr_;
240 ptr_ = nullptr;
241 vsl_b_read(bfs,ptr_);
242 }
243 };
244
245 template <class BaseClass>
vsl_b_write(vsl_b_ostream & bfs,const mbl_cloneable_nzptr<BaseClass> & p)246 void vsl_b_write(vsl_b_ostream& bfs, const mbl_cloneable_nzptr<BaseClass>& p)
247 { p.b_write(bfs); }
248
249 template <class BaseClass>
vsl_b_read(vsl_b_istream & bfs,mbl_cloneable_nzptr<BaseClass> & p)250 void vsl_b_read(vsl_b_istream& bfs, mbl_cloneable_nzptr<BaseClass>& p)
251 { p.b_read(bfs); }
252
253 #define MBL_CLONEABLE_PTR_INSTANTIATE(T) /* nothing */
254 #if 0 // was:
255 template <> class mbl_cloneable_ptr<T >; \
256 template <> void vsl_b_write(vsl_b_ostream& bfs, const mbl_cloneable_ptr<T >& p);\
257 template <> void vsl_b_read(vsl_b_istream& bfs, mbl_cloneable_ptr<T >& p);\
258 template <> class mbl_cloneable_nzptr<T >; \
259 template <> void vsl_b_write(vsl_b_ostream& bfs, const mbl_cloneable_nzptr<T >& p);\
260 template <> void vsl_b_read(vsl_b_istream& bfs, mbl_cloneable_nzptr<T >& p)
261 #endif // 0
262
263 #endif // mbl_cloneable_ptr_h
264