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