Simbody  3.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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-12 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 
27 namespace SimTK {
28 
44 template <class T> class ClonePtr {
45 public:
46  typedef T element_type;
47  typedef T* pointer;
48  typedef T& reference;
49 
51  ClonePtr() : p(0) { }
54  explicit ClonePtr(T* obj) : p(obj) { }
57  explicit ClonePtr(T** obj) : p(*obj) { *obj=0; }
63  explicit ClonePtr(const T* obj) : p(obj?obj->clone():0) { }
68  explicit ClonePtr(const T& obj) : p(&obj?obj.clone():0) { }
72  ClonePtr(const ClonePtr& c) : p(c.p?c.p->clone():0) { }
79  { reset(c.p?c.p->clone():0); return *this; }
83  ClonePtr& operator=(const T& t)
84  { reset(&t ? t.clone() :0); return *this; }
89  { reset(tp); return *this; }
90 
92  ~ClonePtr() { delete p; }
93 
98  bool operator==(const ClonePtr& other) const {
99  if (p == other.p) return true; // same object or both empty
100  if (empty() || other.empty()) return false;
101  return getRef()==other.getRef();
102  }
104  bool operator!=(const ClonePtr& other) const {return !((*this)==other);}
105 
111  bool operator<(const ClonePtr& other) const {
112  if (p == other.p) return false; // same object or both empty
113  if (empty()) return true; // empty < !empty
114  if (other.empty()) return false; // !empty > empty
115  return getRef() < other.getRef();
116  }
117 
120  const T* operator->() const { return &getRef(); }
123  T* operator->() { return &updRef(); }
124 
127  const T& operator*() const { return getRef(); }
130  T& operator*() { return updRef(); }
131 
134  const T* operator&() const { return p; }
137  T* operator&() { return p; }
138 
142  operator const T&() const { return getRef(); }
145  operator T&() { return updRef(); }
146 
149  operator bool() const { return !empty(); }
150 
153  T* updPtr() { return p; }
156  const T* getPtr() const { return p; }
157 
161  T& updRef() {
162  SimTK_ERRCHK(p!=0, "ClonePtr::updRef()",
163  "An attempt was made to dereference a null pointer.");
164  return *p;
165  }
169  const T& getRef() const {
170  SimTK_ERRCHK(p!=0, "ClonePtr::getRef()",
171  "An attempt was made to dereference a null pointer.");
172  return *p;
173  }
174 
176  bool empty() const { return p==0; }
179  void clear() { delete p; p=0; }
183  T* release() { T* x=p; p=0; return x; }
188  void reset(T* tp) { if (tp!=p) {delete p; p=tp;} }
194  void reset(T** tpp) {
195  if (*tpp!=p) {delete p; p=*tpp;}
196  *tpp=0;
197  }
200  void swap(ClonePtr& other) {
201  T* otherp = other.release();
202  other.reset(p);
203  reset(otherp);
204  }
205 
206 private:
207  // Warning: ClonePtr must be exactly the same size as type T*. That way
208  // one can reinterpret_cast a T* to a ClonePtr<T> when needed.
209  T* p;
210 };
211 
212 } // namespace SimTK
213 
214 namespace std {
218 template <class T> inline void
220  p1.swap(p2);
221 }
222 
223 } // namespace std
224 
225 #endif // SimTK_SimTKCOMMON_CLONE_PTR_H_