IpSmartPtr.hpp

Go to the documentation of this file.
00001 // Copyright (C) 2004, 2006 International Business Machines and others.
00002 // All Rights Reserved.
00003 // This code is published under the Common Public License.
00004 //
00005 // $Id: IpSmartPtr.hpp 759 2006-07-07 03:07:08Z andreasw $
00006 //
00007 // Authors:  Carl Laird, Andreas Waechter     IBM    2004-08-13
00008 
00009 #ifndef __IPSMARTPTR_HPP__
00010 #define __IPSMARTPTR_HPP__
00011 
00012 #include "IpReferenced.hpp"
00013 
00014 //#define IP_DEBUG_SMARTPTR
00015 #ifdef IP_DEBUG_SMARTPTR
00016 # include "IpDebug.hpp"
00017 #endif
00018 
00019 namespace Ipopt
00020 {
00021 
00164   template<class T>
00165   class SmartPtr : public Referencer
00166   {
00167   public:
00168 #define dbg_smartptr_verbosity 0
00169 
00173     SmartPtr();
00174 
00176     SmartPtr(const SmartPtr<T>& copy);
00177 
00182     /* Don't support this, use dynamic_cast(GetRawPtr(copy))
00183     template <class U>
00184     SmartPtr(const SmartPtr<U> &copy);
00185     */
00186 
00188     SmartPtr(T* ptr);
00189 
00193     ~SmartPtr();
00195 
00200     T* operator->() const;
00201 
00204     T& operator*() const;
00205 
00208     SmartPtr<T>& operator=(T* rhs);
00209 
00213     SmartPtr<T>& operator=(const SmartPtr<T>& rhs);
00214 
00217     template <class U1, class U2>
00218     friend
00219     bool operator==(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs);
00220 
00223     template <class U1, class U2>
00224     friend
00225     bool operator==(const SmartPtr<U1>& lhs, U2* raw_rhs);
00226 
00229     template <class U1, class U2>
00230     friend
00231     bool operator==(U1* lhs, const SmartPtr<U2>& raw_rhs);
00232 
00235     template <class U1, class U2>
00236     friend
00237     bool operator!=(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs);
00238 
00241     template <class U1, class U2>
00242     friend
00243     bool operator!=(const SmartPtr<U1>& lhs, U2* raw_rhs);
00244 
00247     template <class U1, class U2>
00248     friend
00249     bool operator!=(U1* lhs, const SmartPtr<U2>& raw_rhs);
00251 
00264     template <class U>
00265     friend
00266     U* GetRawPtr(const SmartPtr<U>& smart_ptr);
00267 
00269     template <class U>
00270     friend
00271     SmartPtr<const U> ConstPtr(const SmartPtr<U>& smart_ptr);
00272 
00277     template <class U>
00278     friend
00279     bool IsValid(const SmartPtr<U>& smart_ptr);
00280 
00285     template <class U>
00286     friend
00287     bool IsNull(const SmartPtr<U>& smart_ptr);
00289 
00290   private:
00294     T* ptr_;
00295 
00299     SmartPtr<T>& SetFromRawPtr_(T* rhs);
00300 
00304     SmartPtr<T>& SetFromSmartPtr_(const SmartPtr<T>& rhs);
00305 
00307     void ReleasePointer_();
00309   };
00310 
00313   template <class U>
00314   U* GetRawPtr(const SmartPtr<U>& smart_ptr);
00315 
00316   template <class U>
00317   SmartPtr<const U> ConstPtr(const SmartPtr<U>& smart_ptr);
00318 
00319   template <class U>
00320   bool IsNull(const SmartPtr<U>& smart_ptr);
00321 
00322   template <class U>
00323   bool IsValid(const SmartPtr<U>& smart_ptr);
00324 
00325   template <class U1, class U2>
00326   bool operator==(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs);
00327 
00328   template <class U1, class U2>
00329   bool operator==(const SmartPtr<U1>& lhs, U2* raw_rhs);
00330 
00331   template <class U1, class U2>
00332   bool operator==(U1* lhs, const SmartPtr<U2>& raw_rhs);
00333 
00334   template <class U1, class U2>
00335   bool operator!=(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs);
00336 
00337   template <class U1, class U2>
00338   bool operator!=(const SmartPtr<U1>& lhs, U2* raw_rhs);
00339 
00340   template <class U1, class U2>
00341   bool operator!=(U1* lhs, const SmartPtr<U2>& raw_rhs);
00342 
00344 
00345 
00346   template <class T>
00347   SmartPtr<T>::SmartPtr()
00348       :
00349       ptr_(NULL)
00350   {
00351 #ifdef IP_DEBUG_SMARTPTR
00352     DBG_START_METH("SmartPtr<T>::SmartPtr()", dbg_smartptr_verbosity);
00353 #endif
00354 
00355 #ifdef CHECK_SMARTPTR
00356 
00357     const ReferencedObject* trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_
00358     = ptr_;
00359     trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_ = NULL;
00360 #endif
00361 
00362   }
00363 
00364 
00365   template <class T>
00366   SmartPtr<T>::SmartPtr(const SmartPtr<T>& copy)
00367       :
00368       ptr_(NULL)
00369   {
00370 #ifdef IP_DEBUG_SMARTPTR
00371     DBG_START_METH("SmartPtr<T>::SmartPtr(const SmartPtr<T>& copy)", dbg_smartptr_verbosity);
00372 #endif
00373 
00374 #ifdef CHECK_SMARTPTR
00375 
00376     const ReferencedObject* trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_
00377     = ptr_;
00378     trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_ = NULL;
00379 #endif
00380 
00381     (void) SetFromSmartPtr_(copy);
00382   }
00383 
00384 
00385   /* Don't support this, use dynamic_cast(GetRawPtr(copy))
00386   template <class T>
00387   template <class U> SmartPtr<T>::SmartPtr(const SmartPtr<U>& copy)
00388    :
00389    ptr_(NULL)
00390    {
00391      DBG_START_METH("SmartPtr<T>::SmartPtr(const SmartPtr<U>& copy)", dbg_smartptr_verbosity);
00392      
00393      U* raw_U_ptr = GetRawPtr(copy);
00394      
00395      // try to cast to type T
00396      T* raw_T_ptr = dynamic_cast<T*>(raw_U_ptr);
00397      
00398      // Don't try to point to type U with a 
00399      // type T SmartPtr if the types U & T 
00400      // are not related
00401      DBG_ASSERT(raw_T_ptr);
00402      
00403      (void) SetFromRawPtr_(raw_T_ptr);
00404    }
00405    */
00406 
00407 
00408   template <class T>
00409   SmartPtr<T>::SmartPtr(T* ptr)
00410       :
00411       ptr_(NULL)
00412   {
00413 #ifdef IP_DEBUG_SMARTPTR
00414     DBG_START_METH("SmartPtr<T>::SmartPtr(T* ptr)", dbg_smartptr_verbosity);
00415 #endif
00416 
00417 #ifdef CHECK_SMARTPTR
00418 
00419     const ReferencedObject* trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_
00420     = ptr_;
00421     trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_ = NULL;
00422 #endif
00423 
00424     (void) SetFromRawPtr_(ptr);
00425   }
00426 
00427   template <class T>
00428   SmartPtr<T>::~SmartPtr()
00429   {
00430 #ifdef IP_DEBUG_SMARTPTR
00431     DBG_START_METH("SmartPtr<T>::~SmartPtr(T* ptr)", dbg_smartptr_verbosity);
00432 #endif
00433 
00434     ReleasePointer_();
00435   }
00436 
00437 
00438   template <class T>
00439   T* SmartPtr<T>::operator->() const
00440   {
00441 #ifdef IP_DEBUG_SMARTPTR
00442     DBG_START_METH("T* SmartPtr<T>::operator->()", dbg_smartptr_verbosity);
00443 #endif
00444 
00445     // cannot deref a null pointer
00446 #ifdef IP_DEBUG
00447 
00448     assert(ptr_);
00449 #endif
00450 
00451     return ptr_;
00452   }
00453 
00454 
00455   template <class T>
00456   T& SmartPtr<T>::operator*() const
00457   {
00458 #ifdef IP_DEBUG_SMARTPTR
00459     DBG_START_METH("T& SmartPtr<T>::operator*()", dbg_smartptr_verbosity);
00460 #endif
00461 
00462     // cannot dereference a null pointer
00463 #ifdef IP_DEBUG
00464 
00465     assert(ptr_);
00466 #endif
00467 
00468     return *ptr_;
00469   }
00470 
00471 
00472   template <class T>
00473   SmartPtr<T>& SmartPtr<T>::operator=(T* rhs)
00474   {
00475 #ifdef IP_DEBUG_SMARTPTR
00476     DBG_START_METH("SmartPtr<T>& SmartPtr<T>::operator=(T* rhs)", dbg_smartptr_verbosity);
00477 #endif
00478 
00479     return SetFromRawPtr_(rhs);
00480   }
00481 
00482 
00483   template <class T>
00484   SmartPtr<T>& SmartPtr<T>::operator=(const SmartPtr<T>& rhs)
00485   {
00486 #ifdef IP_DEBUG_SMARTPTR
00487     DBG_START_METH(
00488       "SmartPtr<T>& SmartPtr<T>::operator=(const SmartPtr<T>& rhs)",
00489       dbg_smartptr_verbosity);
00490 #endif
00491 
00492     return SetFromSmartPtr_(rhs);
00493   }
00494 
00495 
00496   template <class T>
00497   SmartPtr<T>& SmartPtr<T>::SetFromRawPtr_(T* rhs)
00498   {
00499 #ifdef IP_DEBUG_SMARTPTR
00500     DBG_START_METH(
00501       "SmartPtr<T>& SmartPtr<T>::SetFromRawPtr_(T* rhs)", dbg_smartptr_verbosity);
00502 #endif
00503 
00504     // Release any old pointer
00505     ReleasePointer_();
00506 
00507     if (rhs != NULL) {
00508       rhs->AddRef(this);
00509       ptr_ = rhs;
00510       //       const ReferencedObject* r_ptr =
00511       //         dynamic_cast<const ReferencedObject*>(rhs);
00512 
00513       //       // All objects pointed to by a SmartPtr MUST
00514       //       // inherit off of ReferencedObject
00515       //       DBG_ASSERT(r_ptr && "This is not inherited from ReferencedObject");
00516 
00517       //       if (r_ptr) {
00518       //         r_ptr->AddRef(this);
00519       //         ptr_ = rhs;
00520       //       }
00521     }
00522 
00523     return *this;
00524   }
00525 
00526   template <class T>
00527   SmartPtr<T>& SmartPtr<T>::SetFromSmartPtr_(const SmartPtr<T>& rhs)
00528   {
00529 #ifdef IP_DEBUG_SMARTPTR
00530     DBG_START_METH(
00531       "SmartPtr<T>& SmartPtr<T>::SetFromSmartPtr_(const SmartPtr<T>& rhs)",
00532       dbg_smartptr_verbosity);
00533 #endif
00534 
00535     T* ptr = GetRawPtr(rhs);
00536     /* AW: I changed this so that NULL is correctly copied from the
00537        right hand side */
00538     //     if (ptr != NULL) {
00539     //       SetFromRawPtr_(ptr);
00540     //     }
00541     SetFromRawPtr_(ptr);
00542 
00543     return (*this);
00544   }
00545 
00546 
00547   template <class T>
00548   void SmartPtr<T>::ReleasePointer_()
00549   {
00550 #ifdef IP_DEBUG_SMARTPTR
00551     DBG_START_METH(
00552       "void SmartPtr<T>::ReleasePointer()",
00553       dbg_smartptr_verbosity);
00554 #endif
00555 
00556     if (ptr_) {
00557       ptr_->ReleaseRef(this);
00558       if (ptr_->ReferenceCount() == 0) {
00559         delete ptr_;
00560       }
00561       ptr_ = NULL;
00562     }
00563     //     if (ptr_ != NULL) {
00564     //       const ReferencedObject* r_ptr =
00565     //         dynamic_cast<const ReferencedObject*>(ptr_);
00566 
00567     //       r_ptr->ReleaseRef(this);
00568     //       if (r_ptr->ReferenceCount() == 0) {
00569     //         delete ptr_;
00570     //       }
00571     //       ptr_ = NULL;
00572     //     }
00573   }
00574 
00575 
00576   template <class U>
00577   U* GetRawPtr(const SmartPtr<U>& smart_ptr)
00578   {
00579 #ifdef IP_DEBUG_SMARTPTR
00580     DBG_START_FUN(
00581       "T* GetRawPtr(const SmartPtr<T>& smart_ptr)",
00582       0);
00583 #endif
00584 
00585     return smart_ptr.ptr_;
00586   }
00587 
00588   template <class U>
00589   SmartPtr<const U> ConstPtr(const SmartPtr<U>& smart_ptr)
00590   {
00591     // compiler should implicitly cast
00592     return GetRawPtr(smart_ptr);
00593   }
00594 
00595   template <class U>
00596   bool IsValid(const SmartPtr<U>& smart_ptr)
00597   {
00598     return !IsNull(smart_ptr);
00599   }
00600 
00601   template <class U>
00602   bool IsNull(const SmartPtr<U>& smart_ptr)
00603   {
00604 #ifdef IP_DEBUG_SMARTPTR
00605     DBG_START_FUN(
00606       "bool IsNull(const SmartPtr<T>& smart_ptr)",
00607       0);
00608 #endif
00609 
00610     return (smart_ptr.ptr_ == NULL);
00611   }
00612 
00613 
00614   template <class U1, class U2>
00615   bool ComparePointers(const U1* lhs, const U2* rhs)
00616   {
00617 #ifdef IP_DEBUG_SMARTPTR
00618     DBG_START_FUN(
00619       "bool ComparePtrs(const U1* lhs, const U2* rhs)",
00620       dbg_smartptr_verbosity);
00621 #endif
00622 
00623     if (lhs == rhs) {
00624       return true;
00625     }
00626 
00627     // Even if lhs and rhs point to the same object
00628     // with different interfaces U1 and U2, we cannot guarantee that
00629     // the value of the pointers will be equivalent. We can
00630     // guarantee this if we convert to void*
00631     const void* v_lhs = dynamic_cast<const void*>(lhs);
00632     const void* v_rhs = dynamic_cast<const void*>(rhs);
00633     if (v_lhs == v_rhs) {
00634       return true;
00635     }
00636 
00637     // They must not be the same
00638     return false;
00639   }
00640 
00641   template <class U1, class U2>
00642   bool operator==(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs)
00643   {
00644 #ifdef IP_DEBUG_SMARTPTR
00645     DBG_START_FUN(
00646       "bool operator==(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs)",
00647       dbg_smartptr_verbosity);
00648 #endif
00649 
00650     U1* raw_lhs = GetRawPtr(lhs);
00651     U2* raw_rhs = GetRawPtr(rhs);
00652     return ComparePointers(raw_lhs, raw_rhs);
00653   }
00654 
00655   template <class U1, class U2>
00656   bool operator==(const SmartPtr<U1>& lhs, U2* raw_rhs)
00657   {
00658 #ifdef IP_DEBUG_SMARTPTR
00659     DBG_START_FUN(
00660       "bool operator==(SmartPtr<U1>& lhs, U2* rhs)",
00661       dbg_smartptr_verbosity);
00662 #endif
00663 
00664     U1* raw_lhs = GetRawPtr(lhs);
00665     return ComparePointers(raw_lhs, raw_rhs);
00666   }
00667 
00668   template <class U1, class U2>
00669   bool operator==(U1* raw_lhs, const SmartPtr<U2>& rhs)
00670   {
00671 #ifdef IP_DEBUG_SMARTPTR
00672     DBG_START_FUN(
00673       "bool operator==(U1* raw_lhs, SmartPtr<U2>& rhs)",
00674       dbg_smartptr_verbosity);
00675 #endif
00676 
00677     const U2* raw_rhs = GetRawPtr(rhs);
00678     return ComparePointers(raw_lhs, raw_rhs);
00679   }
00680 
00681   template <class U1, class U2>
00682   bool operator!=(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs)
00683   {
00684 #ifdef IP_DEBUG_SMARTPTR
00685     DBG_START_FUN(
00686       "bool operator!=(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs)",
00687       dbg_smartptr_verbosity);
00688 #endif
00689 
00690     bool retValue = operator==(lhs, rhs);
00691     return !retValue;
00692   }
00693 
00694   template <class U1, class U2>
00695   bool operator!=(const SmartPtr<U1>& lhs, U2* raw_rhs)
00696   {
00697 #ifdef IP_DEBUG_SMARTPTR
00698     DBG_START_FUN(
00699       "bool operator!=(SmartPtr<U1>& lhs, U2* rhs)",
00700       dbg_smartptr_verbosity);
00701 #endif
00702 
00703     bool retValue = operator==(lhs, raw_rhs);
00704     return !retValue;
00705   }
00706 
00707   template <class U1, class U2>
00708   bool operator!=(U1* raw_lhs, const SmartPtr<U2>& rhs)
00709   {
00710 #ifdef IP_DEBUG_SMARTPTR
00711     DBG_START_FUN(
00712       "bool operator!=(U1* raw_lhs, SmartPtr<U2>& rhs)",
00713       dbg_smartptr_verbosity);
00714 #endif
00715 
00716     bool retValue = operator==(raw_lhs, rhs);
00717     return !retValue;
00718   }
00719 
00720 } // namespace Ipopt
00721 
00722 #endif
00723 

Generated on Fri Sep 26 07:44:12 2008 for SimTKcore by  doxygen 1.5.6