/build/buildd/coinor-ipopt-3.10.1/Ipopt/src/Common/IpSmartPtr.hpp
Go to the documentation of this file.
00001 // Copyright (C) 2004, 2011 International Business Machines and others.
00002 // All Rights Reserved.
00003 // This code is published under the Eclipse Public License.
00004 //
00005 // $Id: IpSmartPtr.hpp 2005 2011-06-06 12:55:16Z stefan $
00006 //
00007 // Authors:  Carl Laird, Andreas Waechter     IBM    2004-08-13
00008 
00009 #ifndef __IPSMARTPTR_HPP__
00010 #define __IPSMARTPTR_HPP__
00011 
00012 #ifdef HAVE_CSTDDEF
00013 # include <cstddef>
00014 #else
00015 # ifdef HAVE_STDDEF_H
00016 #  include <stddef.h>
00017 # else
00018 #  error "don't have header file for stddef"
00019 # endif
00020 #endif
00021 
00022 #include "IpReferenced.hpp"
00023 
00024 #include "IpDebug.hpp"
00025 #if COIN_IPOPT_CHECKLEVEL > 2
00026 # define IP_DEBUG_SMARTPTR
00027 #endif
00028 
00029 namespace Ipopt
00030 {
00031 
00174   template<class T>
00175   class SmartPtr : public Referencer
00176   {
00177   public:
00178 #define dbg_smartptr_verbosity 0
00179 
00183     SmartPtr();
00184 
00186     SmartPtr(const SmartPtr<T>& copy);
00187 
00189     SmartPtr(T* ptr);
00190 
00194     ~SmartPtr();
00196 
00201     T* operator->() const;
00202 
00205     T& operator*() const;
00206 
00209     SmartPtr<T>& operator=(T* rhs);
00210 
00214     SmartPtr<T>& operator=(const SmartPtr<T>& rhs);
00215 
00218     template <class U1, class U2>
00219     friend
00220     bool operator==(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs);
00221 
00224     template <class U1, class U2>
00225     friend
00226     bool operator==(const SmartPtr<U1>& lhs, U2* raw_rhs);
00227 
00230     template <class U1, class U2>
00231     friend
00232     bool operator==(U1* lhs, const SmartPtr<U2>& raw_rhs);
00233 
00236     template <class U1, class U2>
00237     friend
00238     bool operator!=(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs);
00239 
00242     template <class U1, class U2>
00243     friend
00244     bool operator!=(const SmartPtr<U1>& lhs, U2* raw_rhs);
00245 
00248     template <class U1, class U2>
00249     friend
00250     bool operator!=(U1* lhs, const SmartPtr<U2>& raw_rhs);
00252 
00265     template <class U>
00266     friend
00267     U* GetRawPtr(const SmartPtr<U>& smart_ptr);
00268 
00270     template <class U>
00271     friend
00272     SmartPtr<const U> ConstPtr(const SmartPtr<U>& smart_ptr);
00273 
00278     template <class U>
00279     friend
00280     bool IsValid(const SmartPtr<U>& smart_ptr);
00281 
00286     template <class U>
00287     friend
00288     bool IsNull(const SmartPtr<U>& smart_ptr);
00290 
00291   private:
00295     T* ptr_;
00296 
00300     SmartPtr<T>& SetFromRawPtr_(T* rhs);
00301 
00305     SmartPtr<T>& SetFromSmartPtr_(const SmartPtr<T>& rhs);
00306 
00308     void ReleasePointer_();
00310   };
00311 
00314   template <class U>
00315   U* GetRawPtr(const SmartPtr<U>& smart_ptr);
00316 
00317   template <class U>
00318   SmartPtr<const U> ConstPtr(const SmartPtr<U>& smart_ptr);
00319 
00320   template <class U>
00321   bool IsNull(const SmartPtr<U>& smart_ptr);
00322 
00323   template <class U>
00324   bool IsValid(const SmartPtr<U>& smart_ptr);
00325 
00326   template <class U1, class U2>
00327   bool operator==(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs);
00328 
00329   template <class U1, class U2>
00330   bool operator==(const SmartPtr<U1>& lhs, U2* raw_rhs);
00331 
00332   template <class U1, class U2>
00333   bool operator==(U1* lhs, const SmartPtr<U2>& raw_rhs);
00334 
00335   template <class U1, class U2>
00336   bool operator!=(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs);
00337 
00338   template <class U1, class U2>
00339   bool operator!=(const SmartPtr<U1>& lhs, U2* raw_rhs);
00340 
00341   template <class U1, class U2>
00342   bool operator!=(U1* lhs, const SmartPtr<U2>& raw_rhs);
00343 
00345 
00346 
00347   template <class T>
00348   SmartPtr<T>::SmartPtr()
00349       :
00350       ptr_(0)
00351   {
00352 #ifdef IP_DEBUG_SMARTPTR
00353     DBG_START_METH("SmartPtr<T>::SmartPtr()", dbg_smartptr_verbosity);
00354 #endif
00355 
00356 #ifdef CHECK_SMARTPTR
00357 
00358     const ReferencedObject* trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_
00359     = ptr_;
00360     trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_ = 0;
00361 #endif
00362 
00363   }
00364 
00365 
00366   template <class T>
00367   SmartPtr<T>::SmartPtr(const SmartPtr<T>& copy)
00368       :
00369       ptr_(0)
00370   {
00371 #ifdef IP_DEBUG_SMARTPTR
00372     DBG_START_METH("SmartPtr<T>::SmartPtr(const SmartPtr<T>& copy)", dbg_smartptr_verbosity);
00373 #endif
00374 
00375 #ifdef CHECK_SMARTPTR
00376 
00377     const ReferencedObject* trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_
00378     = ptr_;
00379     trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_ = 0;
00380 #endif
00381 
00382     (void) SetFromSmartPtr_(copy);
00383   }
00384 
00385 
00386   template <class T>
00387   SmartPtr<T>::SmartPtr(T* ptr)
00388       :
00389       ptr_(0)
00390   {
00391 #ifdef IP_DEBUG_SMARTPTR
00392     DBG_START_METH("SmartPtr<T>::SmartPtr(T* ptr)", dbg_smartptr_verbosity);
00393 #endif
00394 
00395 #ifdef CHECK_SMARTPTR
00396 
00397     const ReferencedObject* trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_
00398     = ptr_;
00399     trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_ = 0;
00400 #endif
00401 
00402     (void) SetFromRawPtr_(ptr);
00403   }
00404 
00405   template <class T>
00406   SmartPtr<T>::~SmartPtr()
00407   {
00408 #ifdef IP_DEBUG_SMARTPTR
00409     DBG_START_METH("SmartPtr<T>::~SmartPtr(T* ptr)", dbg_smartptr_verbosity);
00410 #endif
00411 
00412     ReleasePointer_();
00413   }
00414 
00415 
00416   template <class T>
00417   T* SmartPtr<T>::operator->() const
00418   {
00419 #ifdef IP_DEBUG_SMARTPTR
00420     DBG_START_METH("T* SmartPtr<T>::operator->()", dbg_smartptr_verbosity);
00421 #endif
00422 
00423     // cannot deref a null pointer
00424 #if COIN_IPOPT_CHECKLEVEL > 0
00425 
00426     assert(ptr_);
00427 #endif
00428 
00429     return ptr_;
00430   }
00431 
00432 
00433   template <class T>
00434   T& SmartPtr<T>::operator*() const
00435   {
00436 #ifdef IP_DEBUG_SMARTPTR
00437     DBG_START_METH("T& SmartPtr<T>::operator*()", dbg_smartptr_verbosity);
00438 #endif
00439 
00440     // cannot dereference a null pointer
00441 #if COIN_IPOPT_CHECKLEVEL > 0
00442 
00443     assert(ptr_);
00444 #endif
00445 
00446     return *ptr_;
00447   }
00448 
00449 
00450   template <class T>
00451   SmartPtr<T>& SmartPtr<T>::operator=(T* rhs)
00452   {
00453 #ifdef IP_DEBUG_SMARTPTR
00454     DBG_START_METH("SmartPtr<T>& SmartPtr<T>::operator=(T* rhs)", dbg_smartptr_verbosity);
00455 #endif
00456 
00457     return SetFromRawPtr_(rhs);
00458   }
00459 
00460 
00461   template <class T>
00462   SmartPtr<T>& SmartPtr<T>::operator=(const SmartPtr<T>& rhs)
00463   {
00464 #ifdef IP_DEBUG_SMARTPTR
00465     DBG_START_METH(
00466       "SmartPtr<T>& SmartPtr<T>::operator=(const SmartPtr<T>& rhs)",
00467       dbg_smartptr_verbosity);
00468 #endif
00469 
00470     return SetFromSmartPtr_(rhs);
00471   }
00472 
00473 
00474   template <class T>
00475   SmartPtr<T>& SmartPtr<T>::SetFromRawPtr_(T* rhs)
00476   {
00477 #ifdef IP_DEBUG_SMARTPTR
00478     DBG_START_METH(
00479       "SmartPtr<T>& SmartPtr<T>::SetFromRawPtr_(T* rhs)", dbg_smartptr_verbosity);
00480 #endif
00481 
00482     // Release any old pointer
00483     ReleasePointer_();
00484 
00485     if (rhs != 0) {
00486       rhs->AddRef(this);
00487       ptr_ = rhs;
00488     }
00489 
00490     return *this;
00491   }
00492 
00493   template <class T>
00494   SmartPtr<T>& SmartPtr<T>::SetFromSmartPtr_(const SmartPtr<T>& rhs)
00495   {
00496 #ifdef IP_DEBUG_SMARTPTR
00497     DBG_START_METH(
00498       "SmartPtr<T>& SmartPtr<T>::SetFromSmartPtr_(const SmartPtr<T>& rhs)",
00499       dbg_smartptr_verbosity);
00500 #endif
00501 
00502     T* ptr = GetRawPtr(rhs);
00503     /* AW: I changed this so that NULL is correctly copied from the
00504        right hand side */
00505     //     if (ptr != NULL) {
00506     //       SetFromRawPtr_(ptr);
00507     //     }
00508     SetFromRawPtr_(ptr);
00509 
00510     return (*this);
00511   }
00512 
00513 
00514   template <class T>
00515   void SmartPtr<T>::ReleasePointer_()
00516   {
00517 #ifdef IP_DEBUG_SMARTPTR
00518     DBG_START_METH(
00519       "void SmartPtr<T>::ReleasePointer()",
00520       dbg_smartptr_verbosity);
00521 #endif
00522 
00523     if (ptr_) {
00524       ptr_->ReleaseRef(this);
00525       if (ptr_->ReferenceCount() == 0) {
00526         delete ptr_;
00527       }
00528       ptr_ = 0;
00529     }
00530   }
00531 
00532 
00533   template <class U>
00534   U* GetRawPtr(const SmartPtr<U>& smart_ptr)
00535   {
00536 #ifdef IP_DEBUG_SMARTPTR
00537     DBG_START_FUN(
00538       "T* GetRawPtr(const SmartPtr<T>& smart_ptr)",
00539       0);
00540 #endif
00541 
00542     return smart_ptr.ptr_;
00543   }
00544 
00545   template <class U>
00546   SmartPtr<const U> ConstPtr(const SmartPtr<U>& smart_ptr)
00547   {
00548     // compiler should implicitly cast
00549     return GetRawPtr(smart_ptr);
00550   }
00551 
00552   template <class U>
00553   bool IsValid(const SmartPtr<U>& smart_ptr)
00554   {
00555     return !IsNull(smart_ptr);
00556   }
00557 
00558   template <class U>
00559   bool IsNull(const SmartPtr<U>& smart_ptr)
00560   {
00561 #ifdef IP_DEBUG_SMARTPTR
00562     DBG_START_FUN(
00563       "bool IsNull(const SmartPtr<T>& smart_ptr)",
00564       0);
00565 #endif
00566 
00567     return (smart_ptr.ptr_ == 0);
00568   }
00569 
00570 
00571   template <class U1, class U2>
00572   bool ComparePointers(const U1* lhs, const U2* rhs)
00573   {
00574 #ifdef IP_DEBUG_SMARTPTR
00575     DBG_START_FUN(
00576       "bool ComparePtrs(const U1* lhs, const U2* rhs)",
00577       dbg_smartptr_verbosity);
00578 #endif
00579 
00580     if (lhs == rhs) {
00581       return true;
00582     }
00583 
00584     // Even if lhs and rhs point to the same object
00585     // with different interfaces U1 and U2, we cannot guarantee that
00586     // the value of the pointers will be equivalent. We can
00587     // guarantee this if we convert to void*
00588     const void* v_lhs = static_cast<const void*>(lhs);
00589     const void* v_rhs = static_cast<const void*>(rhs);
00590     if (v_lhs == v_rhs) {
00591       return true;
00592     }
00593 
00594     // They must not be the same
00595     return false;
00596   }
00597 
00598   template <class U1, class U2>
00599   bool operator==(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs)
00600   {
00601 #ifdef IP_DEBUG_SMARTPTR
00602     DBG_START_FUN(
00603       "bool operator==(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs)",
00604       dbg_smartptr_verbosity);
00605 #endif
00606 
00607     U1* raw_lhs = GetRawPtr(lhs);
00608     U2* raw_rhs = GetRawPtr(rhs);
00609     return ComparePointers(raw_lhs, raw_rhs);
00610   }
00611 
00612   template <class U1, class U2>
00613   bool operator==(const SmartPtr<U1>& lhs, U2* raw_rhs)
00614   {
00615 #ifdef IP_DEBUG_SMARTPTR
00616     DBG_START_FUN(
00617       "bool operator==(SmartPtr<U1>& lhs, U2* rhs)",
00618       dbg_smartptr_verbosity);
00619 #endif
00620 
00621     U1* raw_lhs = GetRawPtr(lhs);
00622     return ComparePointers(raw_lhs, raw_rhs);
00623   }
00624 
00625   template <class U1, class U2>
00626   bool operator==(U1* raw_lhs, const SmartPtr<U2>& rhs)
00627   {
00628 #ifdef IP_DEBUG_SMARTPTR
00629     DBG_START_FUN(
00630       "bool operator==(U1* raw_lhs, SmartPtr<U2>& rhs)",
00631       dbg_smartptr_verbosity);
00632 #endif
00633 
00634     const U2* raw_rhs = GetRawPtr(rhs);
00635     return ComparePointers(raw_lhs, raw_rhs);
00636   }
00637 
00638   template <class U1, class U2>
00639   bool operator!=(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs)
00640   {
00641 #ifdef IP_DEBUG_SMARTPTR
00642     DBG_START_FUN(
00643       "bool operator!=(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs)",
00644       dbg_smartptr_verbosity);
00645 #endif
00646 
00647     bool retValue = operator==(lhs, rhs);
00648     return !retValue;
00649   }
00650 
00651   template <class U1, class U2>
00652   bool operator!=(const SmartPtr<U1>& lhs, U2* raw_rhs)
00653   {
00654 #ifdef IP_DEBUG_SMARTPTR
00655     DBG_START_FUN(
00656       "bool operator!=(SmartPtr<U1>& lhs, U2* rhs)",
00657       dbg_smartptr_verbosity);
00658 #endif
00659 
00660     bool retValue = operator==(lhs, raw_rhs);
00661     return !retValue;
00662   }
00663 
00664   template <class U1, class U2>
00665   bool operator!=(U1* raw_lhs, const SmartPtr<U2>& rhs)
00666   {
00667 #ifdef IP_DEBUG_SMARTPTR
00668     DBG_START_FUN(
00669       "bool operator!=(U1* raw_lhs, SmartPtr<U2>& rhs)",
00670       dbg_smartptr_verbosity);
00671 #endif
00672 
00673     bool retValue = operator==(raw_lhs, rhs);
00674     return !retValue;
00675   }
00676 
00677 } // namespace Ipopt
00678 
00679 #endif
00680