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