Ipopt
trunk
|
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