Simbody  3.4 (development)
ClonePtr.h
Go to the documentation of this file.
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_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines