Ipopt  trunk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
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$
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 #include "IpDebug.hpp"
00015 #if COIN_IPOPT_CHECKLEVEL > 2
00016 # define IP_DEBUG_SMARTPTR
00017 #endif
00018 #ifndef IPOPT_UNUSED
00019 # if defined(__GNUC__)
00020 #   define IPOPT_UNUSED __attribute__((unused))
00021 # else
00022 #   define IPOPT_UNUSED
00023 # endif
00024 #endif
00025 
00026 namespace Ipopt
00027 {
00028 
00171   template<class T>
00172   class SmartPtr : public Referencer
00173   {
00174   public:
00175 #define ipopt_dbg_smartptr_verbosity 0
00176 
00180     SmartPtr();
00181 
00183     SmartPtr(const SmartPtr<T>& copy);
00184 
00186     template <class U>
00187     SmartPtr(const SmartPtr<U>& copy);
00188 
00190     SmartPtr(T* ptr);
00191 
00195     ~SmartPtr();
00197 
00202     T* operator->() const;
00203 
00206     T& operator*() const;
00207 
00210     SmartPtr<T>& operator=(T* rhs);
00211 
00215     SmartPtr<T>& operator=(const SmartPtr<T>& rhs);
00216 
00220     template <class U>
00221     SmartPtr<T>& operator=(const SmartPtr<U>& rhs);
00222 
00225     template <class U1, class U2>
00226     friend
00227     bool operator==(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs);
00228 
00231     template <class U1, class U2>
00232     friend
00233     bool operator==(const SmartPtr<U1>& lhs, U2* raw_rhs);
00234 
00237     template <class U1, class U2>
00238     friend
00239     bool operator==(U1* lhs, const SmartPtr<U2>& raw_rhs);
00240 
00243     template <class U1, class U2>
00244     friend
00245     bool operator!=(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs);
00246 
00249     template <class U1, class U2>
00250     friend
00251     bool operator!=(const SmartPtr<U1>& lhs, U2* raw_rhs);
00252 
00255     template <class U1, class U2>
00256     friend
00257     bool operator!=(U1* lhs, const SmartPtr<U2>& raw_rhs);
00258 
00261     template <class U>
00262     friend
00263     bool operator<(const SmartPtr<U>& lhs, const SmartPtr<U>& rhs);
00265 
00278     template <class U>
00279     friend
00280     U* GetRawPtr(const SmartPtr<U>& smart_ptr);
00281 
00283     template <class U>
00284     friend
00285     SmartPtr<const U> ConstPtr(const SmartPtr<U>& smart_ptr);
00286 
00291     template <class U>
00292     friend
00293     bool IsValid(const SmartPtr<U>& smart_ptr);
00294 
00299     template <class U>
00300     friend
00301     bool IsNull(const SmartPtr<U>& smart_ptr);
00303 
00304   private:
00308     T* ptr_;
00309 
00313     SmartPtr<T>& SetFromRawPtr_(T* rhs);
00314 
00318     SmartPtr<T>& SetFromSmartPtr_(const SmartPtr<T>& rhs);
00319 
00321     void ReleasePointer_();
00323   };
00324 
00327   template <class U>
00328   U* GetRawPtr(const SmartPtr<U>& smart_ptr);
00329 
00330   template <class U>
00331   SmartPtr<const U> ConstPtr(const SmartPtr<U>& smart_ptr);
00332 
00333   template <class U>
00334   bool IsNull(const SmartPtr<U>& smart_ptr);
00335 
00336   template <class U>
00337   bool IsValid(const SmartPtr<U>& smart_ptr);
00338 
00339   template <class U1, class U2>
00340   bool operator==(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs);
00341 
00342   template <class U1, class U2>
00343   bool operator==(const SmartPtr<U1>& lhs, U2* raw_rhs);
00344 
00345   template <class U1, class U2>
00346   bool operator==(U1* lhs, const SmartPtr<U2>& raw_rhs);
00347 
00348   template <class U1, class U2>
00349   bool operator!=(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs);
00350 
00351   template <class U1, class U2>
00352   bool operator!=(const SmartPtr<U1>& lhs, U2* raw_rhs);
00353 
00354   template <class U1, class U2>
00355   bool operator!=(U1* lhs, const SmartPtr<U2>& raw_rhs);
00356 
00358 
00359 
00360   template <class T>
00361   SmartPtr<T>::SmartPtr()
00362       :
00363       ptr_(0)
00364   {
00365 #ifdef IP_DEBUG_SMARTPTR
00366     DBG_START_METH("SmartPtr<T>::SmartPtr()", ipopt_dbg_smartptr_verbosity);
00367 #endif
00368 
00369 #ifndef NDEBUG
00370     const ReferencedObject* IPOPT_UNUSED trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_ = ptr_;
00371 #endif
00372 
00373   }
00374 
00375 
00376   template <class T>
00377   SmartPtr<T>::SmartPtr(const SmartPtr<T>& copy)
00378       :
00379       ptr_(0)
00380   {
00381 #ifdef IP_DEBUG_SMARTPTR
00382     DBG_START_METH("SmartPtr<T>::SmartPtr(const SmartPtr<T>& copy)", ipopt_dbg_smartptr_verbosity);
00383 #endif
00384 
00385 #ifndef NDEBUG
00386     const ReferencedObject* IPOPT_UNUSED trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_ = ptr_;
00387 #endif
00388 
00389     (void) SetFromSmartPtr_(copy);
00390   }
00391 
00392 
00393   template <class T>
00394   template <class U>
00395   SmartPtr<T>::SmartPtr(const SmartPtr<U>& copy)
00396       :
00397       ptr_(0)
00398   {
00399 #ifdef IP_DEBUG_SMARTPTR
00400     DBG_START_METH("SmartPtr<T>::SmartPtr(const SmartPtr<U>& copy)", ipopt_dbg_smartptr_verbosity);
00401 #endif
00402 
00403 #ifndef NDEBUG
00404     const ReferencedObject* IPOPT_UNUSED trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_ = ptr_;
00405 #endif
00406 
00407     (void) SetFromSmartPtr_(GetRawPtr(copy));
00408   }
00409 
00410 
00411   template <class T>
00412   SmartPtr<T>::SmartPtr(T* ptr)
00413       :
00414       ptr_(0)
00415   {
00416 #ifdef IP_DEBUG_SMARTPTR
00417     DBG_START_METH("SmartPtr<T>::SmartPtr(T* ptr)", ipopt_dbg_smartptr_verbosity);
00418 #endif
00419 
00420 #ifndef NDEBUG
00421     const ReferencedObject* IPOPT_UNUSED trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_ = ptr_;
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)", ipopt_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->()", ipopt_dbg_smartptr_verbosity);
00443 #endif
00444 
00445     // cannot deref a null pointer
00446 #if COIN_IPOPT_CHECKLEVEL > 0
00447     assert(ptr_);
00448 #endif
00449 
00450     return ptr_;
00451   }
00452 
00453 
00454   template <class T>
00455   T& SmartPtr<T>::operator*() const
00456   {
00457 #ifdef IP_DEBUG_SMARTPTR
00458     DBG_START_METH("T& SmartPtr<T>::operator*()", ipopt_dbg_smartptr_verbosity);
00459 #endif
00460 
00461     // cannot dereference a null pointer
00462 #if COIN_IPOPT_CHECKLEVEL > 0
00463     assert(ptr_);
00464 #endif
00465 
00466     return *ptr_;
00467   }
00468 
00469 
00470   template <class T>
00471   SmartPtr<T>& SmartPtr<T>::operator=(T* rhs)
00472   {
00473 #ifdef IP_DEBUG_SMARTPTR
00474     DBG_START_METH("SmartPtr<T>& SmartPtr<T>::operator=(T* rhs)", ipopt_dbg_smartptr_verbosity);
00475 #endif
00476 
00477     return SetFromRawPtr_(rhs);
00478   }
00479 
00480 
00481   template <class T>
00482   SmartPtr<T>& SmartPtr<T>::operator=(const SmartPtr<T>& rhs)
00483   {
00484 #ifdef IP_DEBUG_SMARTPTR
00485     DBG_START_METH(
00486       "SmartPtr<T>& SmartPtr<T>::operator=(const SmartPtr<T>& rhs)",
00487       ipopt_dbg_smartptr_verbosity);
00488 #endif
00489 
00490     return SetFromSmartPtr_(rhs);
00491   }
00492 
00493 
00494   template <class T>
00495   template <class U>
00496   SmartPtr<T>& SmartPtr<T>::operator=(const SmartPtr<U>& rhs)
00497   {
00498 #ifdef IP_DEBUG_SMARTPTR
00499     DBG_START_METH(
00500       "SmartPtr<T>& SmartPtr<T>::operator=(const SmartPtr<U>& rhs)",
00501       ipopt_dbg_smartptr_verbosity);
00502 #endif
00503 
00504     return SetFromSmartPtr_(GetRawPtr(rhs));
00505   }
00506 
00507 
00508   template <class T>
00509   SmartPtr<T>& SmartPtr<T>::SetFromRawPtr_(T* rhs)
00510   {
00511 #ifdef IP_DEBUG_SMARTPTR
00512     DBG_START_METH(
00513       "SmartPtr<T>& SmartPtr<T>::SetFromRawPtr_(T* rhs)", ipopt_dbg_smartptr_verbosity);
00514 #endif
00515 
00516     if (rhs != 0)
00517       rhs->AddRef(this);
00518 
00519     // Release any old pointer
00520     ReleasePointer_();
00521 
00522     ptr_ = rhs;
00523 
00524     return *this;
00525   }
00526 
00527   template <class T>
00528   SmartPtr<T>& SmartPtr<T>::SetFromSmartPtr_(const SmartPtr<T>& rhs)
00529   {
00530 #ifdef IP_DEBUG_SMARTPTR
00531     DBG_START_METH(
00532       "SmartPtr<T>& SmartPtr<T>::SetFromSmartPtr_(const SmartPtr<T>& rhs)",
00533       ipopt_dbg_smartptr_verbosity);
00534 #endif
00535 
00536     SetFromRawPtr_(GetRawPtr(rhs));
00537 
00538     return (*this);
00539   }
00540 
00541 
00542   template <class T>
00543   void SmartPtr<T>::ReleasePointer_()
00544   {
00545 #ifdef IP_DEBUG_SMARTPTR
00546     DBG_START_METH(
00547       "void SmartPtr<T>::ReleasePointer()",
00548       ipopt_dbg_smartptr_verbosity);
00549 #endif
00550 
00551     if (ptr_) {
00552       ptr_->ReleaseRef(this);
00553       if (ptr_->ReferenceCount() == 0)
00554         delete ptr_;
00555     }
00556   }
00557 
00558 
00559   template <class U>
00560   U* GetRawPtr(const SmartPtr<U>& smart_ptr)
00561   {
00562 #ifdef IP_DEBUG_SMARTPTR
00563     DBG_START_FUN(
00564       "T* GetRawPtr(const SmartPtr<T>& smart_ptr)",
00565       0);
00566 #endif
00567 
00568     return smart_ptr.ptr_;
00569   }
00570 
00571   template <class U>
00572   SmartPtr<const U> ConstPtr(const SmartPtr<U>& smart_ptr)
00573   {
00574     // compiler should implicitly cast
00575     return GetRawPtr(smart_ptr);
00576   }
00577 
00578   template <class U>
00579   bool IsValid(const SmartPtr<U>& smart_ptr)
00580   {
00581     return !IsNull(smart_ptr);
00582   }
00583 
00584   template <class U>
00585   bool IsNull(const SmartPtr<U>& smart_ptr)
00586   {
00587 #ifdef IP_DEBUG_SMARTPTR
00588     DBG_START_FUN(
00589       "bool IsNull(const SmartPtr<T>& smart_ptr)",
00590       0);
00591 #endif
00592 
00593     return (smart_ptr.ptr_ == 0);
00594   }
00595 
00596 
00597   template <class U1, class U2>
00598   bool ComparePointers(const U1* lhs, const U2* rhs)
00599   {
00600 #ifdef IP_DEBUG_SMARTPTR
00601     DBG_START_FUN(
00602       "bool ComparePtrs(const U1* lhs, const U2* rhs)",
00603       ipopt_dbg_smartptr_verbosity);
00604 #endif
00605 
00606     // Even if lhs and rhs point to the same object
00607     // with different interfaces U1 and U2, we cannot guarantee that
00608     // the value of the pointers will be equivalent. We can
00609     // guarantee this if we convert to ReferencedObject* (see also #162)
00610     const ReferencedObject* v_lhs = lhs;
00611     const ReferencedObject* v_rhs = rhs;
00612 
00613     return v_lhs == v_rhs;
00614   }
00615 
00616   template <class U1, class U2>
00617   bool operator==(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs)
00618   {
00619 #ifdef IP_DEBUG_SMARTPTR
00620     DBG_START_FUN(
00621       "bool operator==(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs)",
00622       ipopt_dbg_smartptr_verbosity);
00623 #endif
00624 
00625     U1* raw_lhs = GetRawPtr(lhs);
00626     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, U2* raw_rhs)
00632   {
00633 #ifdef IP_DEBUG_SMARTPTR
00634     DBG_START_FUN(
00635       "bool operator==(SmartPtr<U1>& lhs, U2* rhs)",
00636       ipopt_dbg_smartptr_verbosity);
00637 #endif
00638 
00639     U1* raw_lhs = GetRawPtr(lhs);
00640     return ComparePointers(raw_lhs, raw_rhs);
00641   }
00642 
00643   template <class U1, class U2>
00644   bool operator==(U1* raw_lhs, const SmartPtr<U2>& rhs)
00645   {
00646 #ifdef IP_DEBUG_SMARTPTR
00647     DBG_START_FUN(
00648       "bool operator==(U1* raw_lhs, SmartPtr<U2>& rhs)",
00649       ipopt_dbg_smartptr_verbosity);
00650 #endif
00651 
00652     const U2* raw_rhs = GetRawPtr(rhs);
00653     return ComparePointers(raw_lhs, raw_rhs);
00654   }
00655 
00656   template <class U1, class U2>
00657   bool operator!=(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs)
00658   {
00659 #ifdef IP_DEBUG_SMARTPTR
00660     DBG_START_FUN(
00661       "bool operator!=(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs)",
00662       ipopt_dbg_smartptr_verbosity);
00663 #endif
00664 
00665     bool retValue = operator==(lhs, rhs);
00666     return !retValue;
00667   }
00668 
00669   template <class U1, class U2>
00670   bool operator!=(const SmartPtr<U1>& lhs, U2* raw_rhs)
00671   {
00672 #ifdef IP_DEBUG_SMARTPTR
00673     DBG_START_FUN(
00674       "bool operator!=(SmartPtr<U1>& lhs, U2* rhs)",
00675       ipopt_dbg_smartptr_verbosity);
00676 #endif
00677 
00678     bool retValue = operator==(lhs, raw_rhs);
00679     return !retValue;
00680   }
00681 
00682   template <class U1, class U2>
00683   bool operator!=(U1* raw_lhs, const SmartPtr<U2>& rhs)
00684   {
00685 #ifdef IP_DEBUG_SMARTPTR
00686     DBG_START_FUN(
00687       "bool operator!=(U1* raw_lhs, SmartPtr<U2>& rhs)",
00688       ipopt_dbg_smartptr_verbosity);
00689 #endif
00690 
00691     bool retValue = operator==(raw_lhs, rhs);
00692     return !retValue;
00693   }
00694 
00695   template <class T>
00696   void swap(SmartPtr<T>& a, SmartPtr<T>& b)
00697   {
00698 #ifdef IP_DEBUG_REFERENCED
00699     SmartPtr<T> tmp(a);
00700     a = b;
00701     b = tmp;
00702 #else
00703     std::swap(a.prt_, b.ptr_);
00704 #endif
00705   }
00706 
00707   template <class T>
00708   bool operator<(const SmartPtr<T>& lhs, const SmartPtr<T>& rhs)
00709   {
00710     return lhs.ptr_ < rhs.ptr_;
00711   }
00712 
00713   template <class T>
00714   bool operator> (const SmartPtr<T>& lhs, const SmartPtr<T>& rhs)
00715   {
00716     return rhs < lhs;
00717   }
00718 
00719   template <class T> bool
00720   operator<=(const SmartPtr<T>& lhs, const SmartPtr<T>& rhs)
00721   {
00722     return !( rhs < lhs );
00723   }
00724 
00725   template <class T> bool
00726   operator>=(const SmartPtr<T>& lhs, const SmartPtr<T>& rhs)
00727   {
00728     return !( lhs < rhs );
00729   }
00730 } // namespace Ipopt
00731 
00732 #undef ipopt_dbg_smartptr_verbosity
00733 
00734 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines