Simbody  3.7
ClonePtr.h
Go to the documentation of this file.
1 #ifndef SimTK_SimTKCOMMON_CLONE_PTR_H_
2 #define SimTK_SimTKCOMMON_CLONE_PTR_H_
3 
4 /* -------------------------------------------------------------------------- *
5  * Simbody(tm): SimTKcommon *
6  * -------------------------------------------------------------------------- *
7  * This is part of the SimTK biosimulation toolkit originating from *
8  * Simbios, the NIH National Center for Physics-Based Simulation of *
9  * Biological Structures at Stanford, funded under the NIH Roadmap for *
10  * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. *
11  * *
12  * Portions copyright (c) 2005-15 Stanford University and the Authors. *
13  * Authors: Michael Sherman *
14  * Contributors: *
15  * *
16  * Licensed under the Apache License, Version 2.0 (the "License"); you may *
17  * not use this file except in compliance with the License. You may obtain a *
18  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. *
19  * *
20  * Unless required by applicable law or agreed to in writing, software *
21  * distributed under the License is distributed on an "AS IS" BASIS, *
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
23  * See the License for the specific language governing permissions and *
24  * limitations under the License. *
25  * -------------------------------------------------------------------------- */
26 
28 
29 #include <memory>
30 #include <iosfwd>
31 #include <cassert>
32 #include <utility>
33 
34 namespace SimTK {
35 
55 template <class T> class ClonePtr {
56 public:
57  typedef T element_type;
58  typedef T* pointer;
59  typedef T& reference;
60 
67  ClonePtr() noexcept : p(nullptr) {}
68 
72  ClonePtr(std::nullptr_t) noexcept : ClonePtr() {}
73 
76  explicit ClonePtr(T* x) noexcept : p(x) {}
77 
82  explicit ClonePtr(const T* x) : ClonePtr(cloneOrNull(x)) {}
83 
88  explicit ClonePtr(const T& x) : ClonePtr(&x) {}
89 
93  ClonePtr(const ClonePtr& src) : p(cloneOrNull(src.p)) {}
94 
99  template <class U>
100  ClonePtr(const ClonePtr<U>& src) : p(cloneOrNull(src.p)) {}
101 
105  ClonePtr(ClonePtr&& src) noexcept : p(src.release()) {}
106 
111  template <class U>
112  ClonePtr(ClonePtr<U>&& src) noexcept : p(src.release()) {}
123  ClonePtr& operator=(const ClonePtr& src) {
124  if (&src != this) {
125  assert((p != src.p) || !p); // can't be same ptr unless null
126  reset(cloneOrNull(src.p));
127  }
128  return *this;
129  }
130 
137  template <class U>
139  // The source can't be the same container as this one since they are
140  // different types. The managed pointers should never be the same either
141  // since ClonePtrs represent unique ownership. (OK if both nullptr.)
142  assert((p != static_cast<const T*>(src.p)) || !p);
143 
144  reset(cloneOrNull(src.p));
145  return *this;
146  }
147 
152  ClonePtr& operator=(ClonePtr&& src) noexcept {
153  if (&src != this) {
154  assert((p != src.p) || !p); // can't be same ptr unless null
155  reset(src.p); src.p = nullptr;
156  }
157  return *this;
158  }
159 
164  template <class U>
165  ClonePtr& operator=(ClonePtr<U>&& src) noexcept {
166  // The source can't be the same container as this one since they are
167  // different types. The managed pointers should never be the same either
168  // since ClonePtrs represent unique ownership. (OK if both nullptr.)
169  assert((p != static_cast<const T*>(src.p)) || !p);
170  reset(src.p); src.p = nullptr;
171  return *this;
172  }
173 
177  ClonePtr& operator=(const T& x)
178  { reset(cloneOrNull(&x)); return *this; }
179 
183  ClonePtr& operator=(T* x) noexcept
184  { reset(x); return *this; }
191  ~ClonePtr() noexcept {reset();}
202  const T* get() const noexcept {return p;}
203 
208  T* upd() noexcept {return p;}
209 
213  const T& getRef() const {
214  SimTK_ERRCHK(!empty(), "ClonePtr::getRef()",
215  "An attempt was made to dereference a null pointer.");
216  return *get();
217  }
218 
221  T& updRef() {
222  SimTK_ERRCHK(!empty(), "ClonePtr::updRef()",
223  "An attempt was made to dereference a null pointer.");
224  return *upd();
225  }
226 
229  const T* operator->() const { return &getRef(); }
230 
233  T* operator->() { return &updRef(); }
234 
237  const T& operator*() const {return getRef();}
238 
241  T& operator*() {return updRef();}
251  void reset() noexcept {
252  delete p;
253  p = nullptr;
254  }
255 
260  void reset(T* x) noexcept {
261  if (x != p) {
262  delete p;
263  p = x;
264  }
265  }
266 
271  void swap(ClonePtr& other) noexcept {
272  std::swap(p, other.p);
273  }
274 
278  bool empty() const noexcept {return !p;} // count should be null also
279 
282  explicit operator bool() const noexcept {return !empty();}
283 
287  T* release() noexcept {
288  T* save = p;
289  p = nullptr;
290  return save;
291  }
292 
295  DEPRECATED_14("use get() instead")
296  const T* getPtr() const noexcept {return get();}
299  DEPRECATED_14("use upd() instead")
300  T* updPtr() noexcept {return upd();}
302  DEPRECATED_14("use reset() instead")
303  void clear() noexcept {reset();}
304 
307 private:
308 template <class U> friend class ClonePtr;
309 
310  // If src is non-null, clone it; otherwise return nullptr.
311  static T* cloneOrNull(const T* src) {
312  return src ? src->clone() : nullptr;
313  }
314 
315  T* p; // this may be null
316 };
317 
318 
319 
320 //==============================================================================
321 // SimTK namespace-scope functions
322 //==============================================================================
323 // These namespace-scope functions will be resolved by the compiler using
324 // "Koenig lookup" which examines the arguments' namespaces first.
325 // See Herb Sutter's discussion here: http://www.gotw.ca/publications/mill08.htm.
326 
331 template <class T> inline void
332 swap(ClonePtr<T>& p1, ClonePtr<T>& p2) noexcept {
333  p1.swap(p2);
334 }
335 
339 template <class charT, class traits, class T>
340 inline std::basic_ostream<charT,traits>&
341 operator<<(std::basic_ostream<charT,traits>& os,
342  const ClonePtr<T>& p)
343 { os << p.get(); return os; }
344 
350 template <class T, class U>
351 inline bool operator==(const ClonePtr<T>& lhs,
352  const ClonePtr<U>& rhs)
353 { return lhs.get() == rhs.get(); }
354 
357 template <class T>
358 inline bool operator==(const ClonePtr<T>& lhs, std::nullptr_t)
359 { return lhs.empty(); }
360 
363 template <class T>
364 inline bool operator==(std::nullptr_t, const ClonePtr<T>& rhs)
365 { return rhs.empty(); }
366 
373 template <class T, class U>
374 inline bool operator<(const ClonePtr<T>& lhs,
375  const ClonePtr<U>& rhs)
376 { return lhs.get() < rhs.get(); }
377 
382 template <class T>
383 inline bool operator<(const ClonePtr<T>& lhs, std::nullptr_t)
384 { return false; }
385 
390 template <class T>
391 inline bool operator<(std::nullptr_t, const ClonePtr<T>& rhs)
392 { return !rhs.empty(); }
393 
394 
395 // These functions are derived from operator== and operator<.
396 
399 template <class T, class U>
400 inline bool operator!=(const ClonePtr<T>& lhs,
401  const ClonePtr<U>& rhs)
402 { return !(lhs==rhs); }
405 template <class T>
406 inline bool operator!=(const ClonePtr<T>& lhs, std::nullptr_t)
407 { return !(lhs==nullptr); }
410 template <class T>
411 inline bool operator!=(std::nullptr_t, const ClonePtr<T>& rhs)
412 { return !(nullptr==rhs); }
413 
416 template <class T, class U>
417 inline bool operator>(const ClonePtr<T>& lhs,
418  const ClonePtr<U>& rhs)
419 { return rhs < lhs; }
422 template <class T>
423 inline bool operator>(const ClonePtr<T>& lhs, std::nullptr_t)
424 { return nullptr < lhs; }
425 
428 template <class T>
429 inline bool operator>(std::nullptr_t, const ClonePtr<T>& rhs)
430 { return rhs < nullptr; }
431 
432 
435 template <class T, class U>
436 inline bool operator>=(const ClonePtr<T>& lhs,
437  const ClonePtr<U>& rhs)
438 { return !(lhs < rhs); }
441 template <class T>
442 inline bool operator>=(const ClonePtr<T>& lhs, std::nullptr_t)
443 { return !(lhs < nullptr); }
444 
447 template <class T>
448 inline bool operator>=(std::nullptr_t, const ClonePtr<T>& rhs)
449 { return !(nullptr < rhs); }
450 
451 
455 template <class T, class U>
456 inline bool operator<=(const ClonePtr<T>& lhs,
457  const ClonePtr<U>& rhs)
458 { return !(rhs < lhs); }
462 template <class T>
463 inline bool operator<=(const ClonePtr<T>& lhs, std::nullptr_t)
464 { return !(nullptr < lhs); }
468 template <class T>
469 inline bool operator<=(std::nullptr_t, const ClonePtr<T>& rhs)
470 { return !(rhs < nullptr); }
471 
472 } // namespace SimTK
473 
474 #endif // SimTK_SimTKCOMMON_CLONE_PTR_H_
T * upd() noexcept
Return a writable pointer to the contained object if any, or nullptr.
Definition: ClonePtr.h:208
void reset() noexcept
Make this container empty if it isn&#39;t already, destructing the contained object if there is one...
Definition: ClonePtr.h:251
bool operator>(const ClonePtr< T > &lhs, std::nullptr_t)
nullptr greater-than test defined as nullptr < lhs.
Definition: ClonePtr.h:423
This is the top-level SimTK namespace into which all SimTK names are placed to avoid collision with o...
Definition: Assembler.h:37
void reset(T *x) noexcept
Replace the contents of this container with the supplied heap-allocated object, taking over ownership...
Definition: ClonePtr.h:260
ClonePtr(ClonePtr &&src) noexcept
Move constructor is very fast and leaves the source empty.
Definition: ClonePtr.h:105
ClonePtr(const ClonePtr< U > &src)
Deep copy construction from a compatible ClonePtr.
Definition: ClonePtr.h:100
~ClonePtr() noexcept
Destructor deletes the contained object.
Definition: ClonePtr.h:191
bool operator!=(const ClonePtr< T > &lhs, std::nullptr_t)
nullptr inequality test defined as !(lhs==nullptr).
Definition: ClonePtr.h:406
ClonePtr & operator=(const ClonePtr &src)
Copy assignment replaces the currently-held object by a copy of the object held in the source contain...
Definition: ClonePtr.h:123
bool operator>=(std::nullptr_t, const ClonePtr< T > &rhs)
nullptr greater-or-equal test defined as !(nullptr < rhs).
Definition: ClonePtr.h:448
ClonePtr & operator=(ClonePtr &&src) noexcept
Move assignment replaces the currently-held object by the source object, leaving the source empty...
Definition: ClonePtr.h:152
ClonePtr(ClonePtr< U > &&src) noexcept
Move construction from a compatible ClonePtr.
Definition: ClonePtr.h:112
void swap(ClonePtr< T > &p1, ClonePtr< T > &p2) noexcept
This is an overload of the STL std::swap() algorithm which uses the cheap built-in swap() member of t...
Definition: ClonePtr.h:332
bool operator>(std::nullptr_t, const ClonePtr< T > &rhs)
nullptr greater-than test defined as rhs < nullptr.
Definition: ClonePtr.h:429
#define DEPRECATED_14(MSG)
Definition: SimTKcommon/include/SimTKcommon/internal/common.h:289
T * release() noexcept
Remove the contained object from management by this container and transfer ownership to the caller...
Definition: ClonePtr.h:287
T & updRef()
Return a writable reference to the contained object.
Definition: ClonePtr.h:221
ClonePtr(const T &x)
Given a read-only reference to an object, create a new heap-allocated copy of that object via its clo...
Definition: ClonePtr.h:88
bool operator==(std::nullptr_t, const ClonePtr< T > &rhs)
Comparison against nullptr; same as rhs.empty().
Definition: ClonePtr.h:364
ClonePtr & operator=(const T &x)
This form of assignment replaces the currently-held object by a heap-allocated copy of the source obj...
Definition: ClonePtr.h:177
T element_type
Type of the contained object.
Definition: ClonePtr.h:57
void clear() noexcept
(Deprecated) Use reset() instead.
Definition: ClonePtr.h:303
bool operator!=(const ClonePtr< T > &lhs, const ClonePtr< U > &rhs)
Pointer inequality test defined as !(lhs==rhs).
Definition: ClonePtr.h:400
ClonePtr & operator=(ClonePtr< U > &&src) noexcept
Move assignment from a compatible ClonePtr replaces the currently-held object by the source object...
Definition: ClonePtr.h:165
bool operator!=(std::nullptr_t, const ClonePtr< T > &rhs)
nullptr inequality test defined as !(nullptr==rhs).
Definition: ClonePtr.h:411
Smart pointer with deep copy semantics.
Definition: ClonePtr.h:55
T & operator*()
Return a writable reference to the contained object.
Definition: ClonePtr.h:241
bool operator>=(const ClonePtr< T > &lhs, const ClonePtr< U > &rhs)
Pointer greater-or-equal test defined as !(lhs < rhs).
Definition: ClonePtr.h:436
ClonePtr(const ClonePtr &src)
Copy constructor is deep; the new ClonePtr object contains a new copy of the object in the source...
Definition: ClonePtr.h:93
#define SimTK_ERRCHK(cond, whereChecked, msg)
Definition: ExceptionMacros.h:324
void swap(ClonePtr &other) noexcept
Swap the contents of this ClonePtr with another one, with ownership changing hands but no copying per...
Definition: ClonePtr.h:271
ClonePtr(T *x) noexcept
Given a pointer to a writable heap-allocated object, take over ownership of that object.
Definition: ClonePtr.h:76
Mandatory first inclusion for any Simbody source or header file.
ClonePtr & operator=(T *x) noexcept
This form of assignment replaces the currently-held object by the given source object and takes over ...
Definition: ClonePtr.h:183
ClonePtr(std::nullptr_t) noexcept
Constructor from nullptr is the same as the default constructor.
Definition: ClonePtr.h:72
bool operator==(const ClonePtr< T > &lhs, const ClonePtr< U > &rhs)
Compare for equality the managed pointers contained in two compatible ClonePtr containers.
Definition: ClonePtr.h:351
const T & getRef() const
Return a const reference to the contained object.
Definition: ClonePtr.h:213
T * operator->()
Dereference a writable pointer to the contained object.
Definition: ClonePtr.h:233
bool empty() const noexcept
Return true if this container is empty, which is the state the container is in immediately after defa...
Definition: ClonePtr.h:278
ClonePtr() noexcept
Default constructor stores a nullptr.
Definition: ClonePtr.h:67
bool operator>(const ClonePtr< T > &lhs, const ClonePtr< U > &rhs)
Pointer greater-than test defined as rhs < lhs.
Definition: ClonePtr.h:417
const T * operator->() const
Dereference a const pointer to the contained object.
Definition: ClonePtr.h:229
const T * getPtr() const noexcept
(Deprecated) Same as get().
Definition: ClonePtr.h:296
bool operator==(const ClonePtr< T > &lhs, std::nullptr_t)
Comparison against nullptr; same as lhs.empty().
Definition: ClonePtr.h:358
T * pointer
Type of a pointer to the contained object.
Definition: ClonePtr.h:58
T * updPtr() noexcept
(Deprecated) Same as upd().
Definition: ClonePtr.h:300
const T & operator*() const
This "dereference" operator returns a const reference to the contained object.
Definition: ClonePtr.h:237
T & reference
Type of a reference to the contained object.
Definition: ClonePtr.h:59
bool operator>=(const ClonePtr< T > &lhs, std::nullptr_t)
nullptr greater-or-equal test defined as !(lhs < nullptr).
Definition: ClonePtr.h:442
ClonePtr & operator=(const ClonePtr< U > &src)
Copy assignment from a compatible ClonePtr.
Definition: ClonePtr.h:138
ClonePtr(const T *x)
Given a pointer to a read-only object, create a new heap-allocated copy of that object via its clone(...
Definition: ClonePtr.h:82
const T * get() const noexcept
Return a const pointer to the contained object if any, or nullptr.
Definition: ClonePtr.h:202