Simbody
3.4 (development)
|
00001 #ifndef SimTK_SimTKCOMMON_CLONE_PTR_H_ 00002 #define SimTK_SimTKCOMMON_CLONE_PTR_H_ 00003 00004 /* -------------------------------------------------------------------------- * 00005 * Simbody(tm): SimTKcommon * 00006 * -------------------------------------------------------------------------- * 00007 * This is part of the SimTK biosimulation toolkit originating from * 00008 * Simbios, the NIH National Center for Physics-Based Simulation of * 00009 * Biological Structures at Stanford, funded under the NIH Roadmap for * 00010 * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. * 00011 * * 00012 * Portions copyright (c) 2005-12 Stanford University and the Authors. * 00013 * Authors: Michael Sherman * 00014 * Contributors: * 00015 * * 00016 * Licensed under the Apache License, Version 2.0 (the "License"); you may * 00017 * not use this file except in compliance with the License. You may obtain a * 00018 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * 00019 * * 00020 * Unless required by applicable law or agreed to in writing, software * 00021 * distributed under the License is distributed on an "AS IS" BASIS, * 00022 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 00023 * See the License for the specific language governing permissions and * 00024 * limitations under the License. * 00025 * -------------------------------------------------------------------------- */ 00026 00027 namespace SimTK { 00028 00044 template <class T> class ClonePtr { 00045 public: 00046 typedef T element_type; 00047 typedef T* pointer; 00048 typedef T& reference; 00049 00051 ClonePtr() : p(0) { } 00054 explicit ClonePtr(T* obj) : p(obj) { } 00057 explicit ClonePtr(T** obj) : p(*obj) { *obj=0; } 00063 explicit ClonePtr(const T* obj) : p(obj?obj->clone():0) { } 00068 explicit ClonePtr(const T& obj) : p(&obj?obj.clone():0) { } 00072 ClonePtr(const ClonePtr& c) : p(c.p?c.p->clone():0) { } 00078 ClonePtr& operator=(const ClonePtr& c) 00079 { reset(c.p?c.p->clone():0); return *this; } 00083 ClonePtr& operator=(const T& t) 00084 { reset(&t ? t.clone() :0); return *this; } 00088 ClonePtr& operator=(T* tp) 00089 { reset(tp); return *this; } 00090 00092 ~ClonePtr() { delete p; } 00093 00098 bool operator==(const ClonePtr& other) const { 00099 if (p == other.p) return true; // same object or both empty 00100 if (empty() || other.empty()) return false; 00101 return getRef()==other.getRef(); 00102 } 00104 bool operator!=(const ClonePtr& other) const {return !((*this)==other);} 00105 00111 bool operator<(const ClonePtr& other) const { 00112 if (p == other.p) return false; // same object or both empty 00113 if (empty()) return true; // empty < !empty 00114 if (other.empty()) return false; // !empty > empty 00115 return getRef() < other.getRef(); 00116 } 00117 00120 const T* operator->() const { return &getRef(); } 00123 T* operator->() { return &updRef(); } 00124 00127 const T& operator*() const { return getRef(); } 00130 T& operator*() { return updRef(); } 00131 00134 const T* operator&() const { return p; } 00137 T* operator&() { return p; } 00138 00142 operator const T&() const { return getRef(); } 00145 operator T&() { return updRef(); } 00146 00149 operator bool() const { return !empty(); } 00150 00153 T* updPtr() { return p; } 00156 const T* getPtr() const { return p; } 00157 00161 T& updRef() { 00162 SimTK_ERRCHK(p!=0, "ClonePtr::updRef()", 00163 "An attempt was made to dereference a null pointer."); 00164 return *p; 00165 } 00169 const T& getRef() const { 00170 SimTK_ERRCHK(p!=0, "ClonePtr::getRef()", 00171 "An attempt was made to dereference a null pointer."); 00172 return *p; 00173 } 00174 00176 bool empty() const { return p==0; } 00179 void clear() { delete p; p=0; } 00183 T* release() { T* x=p; p=0; return x; } 00188 void reset(T* tp) { if (tp!=p) {delete p; p=tp;} } 00194 void reset(T** tpp) { 00195 if (*tpp!=p) {delete p; p=*tpp;} 00196 *tpp=0; 00197 } 00200 void swap(ClonePtr& other) { 00201 T* otherp = other.release(); 00202 other.reset(p); 00203 reset(otherp); 00204 } 00205 00206 private: 00207 // Warning: ClonePtr must be exactly the same size as type T*. That way 00208 // one can reinterpret_cast a T* to a ClonePtr<T> when needed. 00209 T* p; 00210 }; 00211 00212 } // namespace SimTK 00213 00214 namespace std { 00218 template <class T> inline void 00219 swap(SimTK::ClonePtr<T>& p1, SimTK::ClonePtr<T>& p2) { 00220 p1.swap(p2); 00221 } 00222 00223 } // namespace std 00224 00225 #endif // SimTK_SimTKCOMMON_CLONE_PTR_H_