IpSmartPtr.hpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. // Copyright (C) 2004, 2011 International Business Machines and others.
  2. // All Rights Reserved.
  3. // This code is published under the Eclipse Public License.
  4. //
  5. // $Id: IpSmartPtr.hpp 2182 2013-03-30 20:02:18Z stefan $
  6. //
  7. // Authors: Carl Laird, Andreas Waechter IBM 2004-08-13
  8. #ifndef __IPSMARTPTR_HPP__
  9. #define __IPSMARTPTR_HPP__
  10. #include "IpReferenced.hpp"
  11. #include "IpDebug.hpp"
  12. #if COIN_IPOPT_CHECKLEVEL > 2
  13. # define IP_DEBUG_SMARTPTR
  14. #endif
  15. #ifndef IPOPT_UNUSED
  16. # if defined(__GNUC__)
  17. # define IPOPT_UNUSED __attribute__((unused))
  18. # else
  19. # define IPOPT_UNUSED
  20. # endif
  21. #endif
  22. namespace Ipopt
  23. {
  24. /** Template class for Smart Pointers.
  25. * A SmartPtr behaves much like a raw pointer, but manages the lifetime
  26. * of an object, deleting the object automatically. This class implements
  27. * a reference-counting, intrusive smart pointer design, where all
  28. * objects pointed to must inherit off of ReferencedObject, which
  29. * stores the reference count. Although this is intrusive (native types
  30. * and externally authored classes require wrappers to be referenced
  31. * by smart pointers), it is a safer design. A more detailed discussion of
  32. * these issues follows after the usage information.
  33. *
  34. * Usage Example:
  35. * Note: to use the SmartPtr, all objects to which you point MUST
  36. * inherit off of ReferencedObject.
  37. *
  38. * \verbatim
  39. *
  40. * In MyClass.hpp...
  41. *
  42. * #include "IpReferenced.hpp"
  43. * namespace Ipopt {
  44. *
  45. * class MyClass : public ReferencedObject // must derive from ReferencedObject
  46. * {
  47. * ...
  48. * }
  49. * } // namespace Ipopt
  50. *
  51. *
  52. * In my_usage.cpp...
  53. *
  54. * #include "IpSmartPtr.hpp"
  55. * #include "MyClass.hpp"
  56. *
  57. * void func(AnyObject& obj)
  58. * {
  59. * SmartPtr<MyClass> ptr_to_myclass = new MyClass(...);
  60. * // ptr_to_myclass now points to a new MyClass,
  61. * // and the reference count is 1
  62. *
  63. * ...
  64. *
  65. * obj.SetMyClass(ptr_to_myclass);
  66. * // Here, let's assume that AnyObject uses a
  67. * // SmartPtr<MyClass> internally here.
  68. * // Now, both ptr_to_myclass and the internal
  69. * // SmartPtr in obj point to the same MyClass object
  70. * // and its reference count is 2.
  71. *
  72. * ...
  73. *
  74. * // No need to delete ptr_to_myclass, this
  75. * // will be done automatically when the
  76. * // reference count drops to zero.
  77. *
  78. * }
  79. *
  80. * \endverbatim
  81. *
  82. * It is not necessary to use SmartPtr's in all cases where an
  83. * object is used that has been allocated "into" a SmartPtr. It is
  84. * possible to just pass objects by reference or regular pointers,
  85. * even if lower down in the stack a SmartPtr is to be held on to.
  86. * Everything should work fine as long as a pointer created by "new"
  87. * is immediately passed into a SmartPtr, and if SmartPtr's are used
  88. * to hold on to objects.
  89. *
  90. * Other Notes:
  91. * The SmartPtr implements both dereference operators -> & *.
  92. * The SmartPtr does NOT implement a conversion operator to
  93. * the raw pointer. Use the GetRawPtr() method when this
  94. * is necessary. Make sure that the raw pointer is NOT
  95. * deleted.
  96. * The SmartPtr implements the comparison operators == & !=
  97. * for a variety of types. Use these instead of
  98. * \verbatim
  99. * if (GetRawPtr(smrt_ptr) == ptr) // Don't use this
  100. * \endverbatim
  101. * SmartPtr's, as currently implemented, do NOT handle circular references.
  102. * For example: consider a higher level object using SmartPtrs to point to
  103. * A and B, but A and B also point to each other (i.e. A has a SmartPtr
  104. * to B and B has a SmartPtr to A). In this scenario, when the higher
  105. * level object is finished with A and B, their reference counts will
  106. * never drop to zero (since they reference each other) and they
  107. * will not be deleted. This can be detected by memory leak tools like
  108. * valgrind. If the circular reference is necessary, the problem can be
  109. * overcome by a number of techniques:
  110. *
  111. * 1) A and B can have a method that "releases" each other, that is
  112. * they set their internal SmartPtrs to NULL.
  113. * \verbatim
  114. * void AClass::ReleaseCircularReferences()
  115. * {
  116. * smart_ptr_to_B = NULL;
  117. * }
  118. * \endverbatim
  119. * Then, the higher level class can call these methods before
  120. * it is done using A & B.
  121. *
  122. * 2) Raw pointers can be used in A and B to reference each other.
  123. * Here, an implicit assumption is made that the lifetime is
  124. * controlled by the higher level object and that A and B will
  125. * both exist in a controlled manner. Although this seems
  126. * dangerous, in many situations, this type of referencing
  127. * is very controlled and this is reasonably safe.
  128. *
  129. * 3) This SmartPtr class could be redesigned with the Weak/Strong
  130. * design concept. Here, the SmartPtr is identified as being
  131. * Strong (controls lifetime of the object) or Weak (merely
  132. * referencing the object). The Strong SmartPtr increments
  133. * (and decrements) the reference count in ReferencedObject
  134. * but the Weak SmartPtr does not. In the example above,
  135. * the higher level object would have Strong SmartPtrs to
  136. * A and B, but A and B would have Weak SmartPtrs to each
  137. * other. Then, when the higher level object was done with
  138. * A and B, they would be deleted. The Weak SmartPtrs in A
  139. * and B would not decrement the reference count and would,
  140. * of course, not delete the object. This idea is very similar
  141. * to item (2), where it is implied that the sequence of events
  142. * is controlled such that A and B will not call anything using
  143. * their pointers following the higher level delete (i.e. in
  144. * their destructors!). This is somehow safer, however, because
  145. * code can be written (however expensive) to perform run-time
  146. * detection of this situation. For example, the ReferencedObject
  147. * could store pointers to all Weak SmartPtrs that are referencing
  148. * it and, in its destructor, tell these pointers that it is
  149. * dying. They could then set themselves to NULL, or set an
  150. * internal flag to detect usage past this point.
  151. *
  152. * Comments on Non-Intrusive Design:
  153. * In a non-intrusive design, the reference count is stored somewhere other
  154. * than the object being referenced. This means, unless the reference
  155. * counting pointer is the first referencer, it must get a pointer to the
  156. * referenced object from another smart pointer (so it has access to the
  157. * reference count location). In this non-intrusive design, if we are
  158. * pointing to an object with a smart pointer (or a number of smart
  159. * pointers), and we then give another smart pointer the address through
  160. * a RAW pointer, we will have two independent, AND INCORRECT, reference
  161. * counts. To avoid this pitfall, we use an intrusive reference counting
  162. * technique where the reference count is stored in the object being
  163. * referenced.
  164. */
  165. template<class T>
  166. class SmartPtr : public Referencer
  167. {
  168. public:
  169. #define ipopt_dbg_smartptr_verbosity 0
  170. /**@name Constructors/Destructors */
  171. //@{
  172. /** Default constructor, initialized to NULL */
  173. SmartPtr();
  174. /** Copy constructor, initialized from copy of type T */
  175. SmartPtr(const SmartPtr<T>& copy);
  176. /** Copy constructor, initialized from copy of type U */
  177. template <class U>
  178. SmartPtr(const SmartPtr<U>& copy);
  179. /** Constructor, initialized from T* ptr */
  180. SmartPtr(T* ptr);
  181. /** Destructor, automatically decrements the
  182. * reference count, deletes the object if
  183. * necessary.*/
  184. ~SmartPtr();
  185. //@}
  186. /**@name Overloaded operators. */
  187. //@{
  188. /** Overloaded arrow operator, allows the user to call
  189. * methods using the contained pointer. */
  190. T* operator->() const;
  191. /** Overloaded dereference operator, allows the user
  192. * to dereference the contained pointer. */
  193. T& operator*() const;
  194. /** Overloaded equals operator, allows the user to
  195. * set the value of the SmartPtr from a raw pointer */
  196. SmartPtr<T>& operator=(T* rhs);
  197. /** Overloaded equals operator, allows the user to
  198. * set the value of the SmartPtr from another
  199. * SmartPtr */
  200. SmartPtr<T>& operator=(const SmartPtr<T>& rhs);
  201. /** Overloaded equals operator, allows the user to
  202. * set the value of the SmartPtr from another
  203. * SmartPtr of a different type */
  204. template <class U>
  205. SmartPtr<T>& operator=(const SmartPtr<U>& rhs);
  206. /** Overloaded equality comparison operator, allows the
  207. * user to compare the value of two SmartPtrs */
  208. template <class U1, class U2>
  209. friend
  210. bool operator==(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs);
  211. /** Overloaded equality comparison operator, allows the
  212. * user to compare the value of a SmartPtr with a raw pointer. */
  213. template <class U1, class U2>
  214. friend
  215. bool operator==(const SmartPtr<U1>& lhs, U2* raw_rhs);
  216. /** Overloaded equality comparison operator, allows the
  217. * user to compare the value of a raw pointer with a SmartPtr. */
  218. template <class U1, class U2>
  219. friend
  220. bool operator==(U1* lhs, const SmartPtr<U2>& raw_rhs);
  221. /** Overloaded in-equality comparison operator, allows the
  222. * user to compare the value of two SmartPtrs */
  223. template <class U1, class U2>
  224. friend
  225. bool operator!=(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs);
  226. /** Overloaded in-equality comparison operator, allows the
  227. * user to compare the value of a SmartPtr with a raw pointer. */
  228. template <class U1, class U2>
  229. friend
  230. bool operator!=(const SmartPtr<U1>& lhs, U2* raw_rhs);
  231. /** Overloaded in-equality comparison operator, allows the
  232. * user to compare the value of a SmartPtr with a raw pointer. */
  233. template <class U1, class U2>
  234. friend
  235. bool operator!=(U1* lhs, const SmartPtr<U2>& raw_rhs);
  236. /** Overloaded less-than comparison operator, allows the
  237. * user to compare the value of two SmartPtrs */
  238. template <class U>
  239. friend
  240. bool operator<(const SmartPtr<U>& lhs, const SmartPtr<U>& rhs);
  241. //@}
  242. /**@name friend method declarations. */
  243. //@{
  244. /** Returns the raw pointer contained.
  245. * Use to get the value of
  246. * the raw ptr (i.e. to pass to other
  247. * methods/functions, etc.)
  248. * Note: This method does NOT copy,
  249. * therefore, modifications using this
  250. * value modify the underlying object
  251. * contained by the SmartPtr,
  252. * NEVER delete this returned value.
  253. */
  254. template <class U>
  255. friend
  256. U* GetRawPtr(const SmartPtr<U>& smart_ptr);
  257. /** Returns a const pointer */
  258. template <class U>
  259. friend
  260. SmartPtr<const U> ConstPtr(const SmartPtr<U>& smart_ptr);
  261. /** Returns true if the SmartPtr is NOT NULL.
  262. * Use this to check if the SmartPtr is not null
  263. * This is preferred to if(GetRawPtr(sp) != NULL)
  264. */
  265. template <class U>
  266. friend
  267. bool IsValid(const SmartPtr<U>& smart_ptr);
  268. /** Returns true if the SmartPtr is NULL.
  269. * Use this to check if the SmartPtr IsNull.
  270. * This is preferred to if(GetRawPtr(sp) == NULL)
  271. */
  272. template <class U>
  273. friend
  274. bool IsNull(const SmartPtr<U>& smart_ptr);
  275. //@}
  276. private:
  277. /**@name Private Data/Methods */
  278. //@{
  279. /** Actual raw pointer to the object. */
  280. T* ptr_;
  281. /** Set the value of the internal raw pointer
  282. * from another raw pointer, releasing the
  283. * previously referenced object if necessary. */
  284. SmartPtr<T>& SetFromRawPtr_(T* rhs);
  285. /** Set the value of the internal raw pointer
  286. * from a SmartPtr, releasing the previously referenced
  287. * object if necessary. */
  288. SmartPtr<T>& SetFromSmartPtr_(const SmartPtr<T>& rhs);
  289. /** Release the currently referenced object. */
  290. void ReleasePointer_();
  291. //@}
  292. };
  293. /**@name SmartPtr friend function declarations.*/
  294. //@{
  295. template <class U>
  296. U* GetRawPtr(const SmartPtr<U>& smart_ptr);
  297. template <class U>
  298. SmartPtr<const U> ConstPtr(const SmartPtr<U>& smart_ptr);
  299. template <class U>
  300. bool IsNull(const SmartPtr<U>& smart_ptr);
  301. template <class U>
  302. bool IsValid(const SmartPtr<U>& smart_ptr);
  303. template <class U1, class U2>
  304. bool operator==(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs);
  305. template <class U1, class U2>
  306. bool operator==(const SmartPtr<U1>& lhs, U2* raw_rhs);
  307. template <class U1, class U2>
  308. bool operator==(U1* lhs, const SmartPtr<U2>& raw_rhs);
  309. template <class U1, class U2>
  310. bool operator!=(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs);
  311. template <class U1, class U2>
  312. bool operator!=(const SmartPtr<U1>& lhs, U2* raw_rhs);
  313. template <class U1, class U2>
  314. bool operator!=(U1* lhs, const SmartPtr<U2>& raw_rhs);
  315. //@}
  316. template <class T>
  317. SmartPtr<T>::SmartPtr()
  318. :
  319. ptr_(0)
  320. {
  321. #ifdef IP_DEBUG_SMARTPTR
  322. DBG_START_METH("SmartPtr<T>::SmartPtr()", ipopt_dbg_smartptr_verbosity);
  323. #endif
  324. #ifndef NDEBUG
  325. const ReferencedObject* IPOPT_UNUSED trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_ = ptr_;
  326. #endif
  327. }
  328. template <class T>
  329. SmartPtr<T>::SmartPtr(const SmartPtr<T>& copy)
  330. :
  331. ptr_(0)
  332. {
  333. #ifdef IP_DEBUG_SMARTPTR
  334. DBG_START_METH("SmartPtr<T>::SmartPtr(const SmartPtr<T>& copy)", ipopt_dbg_smartptr_verbosity);
  335. #endif
  336. #ifndef NDEBUG
  337. const ReferencedObject* IPOPT_UNUSED trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_ = ptr_;
  338. #endif
  339. (void) SetFromSmartPtr_(copy);
  340. }
  341. template <class T>
  342. template <class U>
  343. SmartPtr<T>::SmartPtr(const SmartPtr<U>& copy)
  344. :
  345. ptr_(0)
  346. {
  347. #ifdef IP_DEBUG_SMARTPTR
  348. DBG_START_METH("SmartPtr<T>::SmartPtr(const SmartPtr<U>& copy)", ipopt_dbg_smartptr_verbosity);
  349. #endif
  350. #ifndef NDEBUG
  351. const ReferencedObject* IPOPT_UNUSED trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_ = ptr_;
  352. #endif
  353. (void) SetFromSmartPtr_(GetRawPtr(copy));
  354. }
  355. template <class T>
  356. SmartPtr<T>::SmartPtr(T* ptr)
  357. :
  358. ptr_(0)
  359. {
  360. #ifdef IP_DEBUG_SMARTPTR
  361. DBG_START_METH("SmartPtr<T>::SmartPtr(T* ptr)", ipopt_dbg_smartptr_verbosity);
  362. #endif
  363. #ifndef NDEBUG
  364. const ReferencedObject* IPOPT_UNUSED trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_ = ptr_;
  365. #endif
  366. (void) SetFromRawPtr_(ptr);
  367. }
  368. template <class T>
  369. SmartPtr<T>::~SmartPtr()
  370. {
  371. #ifdef IP_DEBUG_SMARTPTR
  372. DBG_START_METH("SmartPtr<T>::~SmartPtr(T* ptr)", ipopt_dbg_smartptr_verbosity);
  373. #endif
  374. ReleasePointer_();
  375. }
  376. template <class T>
  377. T* SmartPtr<T>::operator->() const
  378. {
  379. #ifdef IP_DEBUG_SMARTPTR
  380. DBG_START_METH("T* SmartPtr<T>::operator->()", ipopt_dbg_smartptr_verbosity);
  381. #endif
  382. // cannot deref a null pointer
  383. #if COIN_IPOPT_CHECKLEVEL > 0
  384. assert(ptr_);
  385. #endif
  386. return ptr_;
  387. }
  388. template <class T>
  389. T& SmartPtr<T>::operator*() const
  390. {
  391. #ifdef IP_DEBUG_SMARTPTR
  392. DBG_START_METH("T& SmartPtr<T>::operator*()", ipopt_dbg_smartptr_verbosity);
  393. #endif
  394. // cannot dereference a null pointer
  395. #if COIN_IPOPT_CHECKLEVEL > 0
  396. assert(ptr_);
  397. #endif
  398. return *ptr_;
  399. }
  400. template <class T>
  401. SmartPtr<T>& SmartPtr<T>::operator=(T* rhs)
  402. {
  403. #ifdef IP_DEBUG_SMARTPTR
  404. DBG_START_METH("SmartPtr<T>& SmartPtr<T>::operator=(T* rhs)", ipopt_dbg_smartptr_verbosity);
  405. #endif
  406. return SetFromRawPtr_(rhs);
  407. }
  408. template <class T>
  409. SmartPtr<T>& SmartPtr<T>::operator=(const SmartPtr<T>& rhs)
  410. {
  411. #ifdef IP_DEBUG_SMARTPTR
  412. DBG_START_METH(
  413. "SmartPtr<T>& SmartPtr<T>::operator=(const SmartPtr<T>& rhs)",
  414. ipopt_dbg_smartptr_verbosity);
  415. #endif
  416. return SetFromSmartPtr_(rhs);
  417. }
  418. template <class T>
  419. template <class U>
  420. SmartPtr<T>& SmartPtr<T>::operator=(const SmartPtr<U>& rhs)
  421. {
  422. #ifdef IP_DEBUG_SMARTPTR
  423. DBG_START_METH(
  424. "SmartPtr<T>& SmartPtr<T>::operator=(const SmartPtr<U>& rhs)",
  425. ipopt_dbg_smartptr_verbosity);
  426. #endif
  427. return SetFromSmartPtr_(GetRawPtr(rhs));
  428. }
  429. template <class T>
  430. SmartPtr<T>& SmartPtr<T>::SetFromRawPtr_(T* rhs)
  431. {
  432. #ifdef IP_DEBUG_SMARTPTR
  433. DBG_START_METH(
  434. "SmartPtr<T>& SmartPtr<T>::SetFromRawPtr_(T* rhs)", ipopt_dbg_smartptr_verbosity);
  435. #endif
  436. if (rhs != 0)
  437. rhs->AddRef(this);
  438. // Release any old pointer
  439. ReleasePointer_();
  440. ptr_ = rhs;
  441. return *this;
  442. }
  443. template <class T>
  444. SmartPtr<T>& SmartPtr<T>::SetFromSmartPtr_(const SmartPtr<T>& rhs)
  445. {
  446. #ifdef IP_DEBUG_SMARTPTR
  447. DBG_START_METH(
  448. "SmartPtr<T>& SmartPtr<T>::SetFromSmartPtr_(const SmartPtr<T>& rhs)",
  449. ipopt_dbg_smartptr_verbosity);
  450. #endif
  451. SetFromRawPtr_(GetRawPtr(rhs));
  452. return (*this);
  453. }
  454. template <class T>
  455. void SmartPtr<T>::ReleasePointer_()
  456. {
  457. #ifdef IP_DEBUG_SMARTPTR
  458. DBG_START_METH(
  459. "void SmartPtr<T>::ReleasePointer()",
  460. ipopt_dbg_smartptr_verbosity);
  461. #endif
  462. if (ptr_) {
  463. ptr_->ReleaseRef(this);
  464. if (ptr_->ReferenceCount() == 0)
  465. delete ptr_;
  466. }
  467. }
  468. template <class U>
  469. U* GetRawPtr(const SmartPtr<U>& smart_ptr)
  470. {
  471. #ifdef IP_DEBUG_SMARTPTR
  472. DBG_START_FUN(
  473. "T* GetRawPtr(const SmartPtr<T>& smart_ptr)",
  474. 0);
  475. #endif
  476. return smart_ptr.ptr_;
  477. }
  478. template <class U>
  479. SmartPtr<const U> ConstPtr(const SmartPtr<U>& smart_ptr)
  480. {
  481. // compiler should implicitly cast
  482. return GetRawPtr(smart_ptr);
  483. }
  484. template <class U>
  485. bool IsValid(const SmartPtr<U>& smart_ptr)
  486. {
  487. return !IsNull(smart_ptr);
  488. }
  489. template <class U>
  490. bool IsNull(const SmartPtr<U>& smart_ptr)
  491. {
  492. #ifdef IP_DEBUG_SMARTPTR
  493. DBG_START_FUN(
  494. "bool IsNull(const SmartPtr<T>& smart_ptr)",
  495. 0);
  496. #endif
  497. return (smart_ptr.ptr_ == 0);
  498. }
  499. template <class U1, class U2>
  500. bool ComparePointers(const U1* lhs, const U2* rhs)
  501. {
  502. #ifdef IP_DEBUG_SMARTPTR
  503. DBG_START_FUN(
  504. "bool ComparePtrs(const U1* lhs, const U2* rhs)",
  505. ipopt_dbg_smartptr_verbosity);
  506. #endif
  507. // Even if lhs and rhs point to the same object
  508. // with different interfaces U1 and U2, we cannot guarantee that
  509. // the value of the pointers will be equivalent. We can
  510. // guarantee this if we convert to ReferencedObject* (see also #162)
  511. const ReferencedObject* v_lhs = lhs;
  512. const ReferencedObject* v_rhs = rhs;
  513. return v_lhs == v_rhs;
  514. }
  515. template <class U1, class U2>
  516. bool operator==(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs)
  517. {
  518. #ifdef IP_DEBUG_SMARTPTR
  519. DBG_START_FUN(
  520. "bool operator==(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs)",
  521. ipopt_dbg_smartptr_verbosity);
  522. #endif
  523. U1* raw_lhs = GetRawPtr(lhs);
  524. U2* raw_rhs = GetRawPtr(rhs);
  525. return ComparePointers(raw_lhs, raw_rhs);
  526. }
  527. template <class U1, class U2>
  528. bool operator==(const SmartPtr<U1>& lhs, U2* raw_rhs)
  529. {
  530. #ifdef IP_DEBUG_SMARTPTR
  531. DBG_START_FUN(
  532. "bool operator==(SmartPtr<U1>& lhs, U2* rhs)",
  533. ipopt_dbg_smartptr_verbosity);
  534. #endif
  535. U1* raw_lhs = GetRawPtr(lhs);
  536. return ComparePointers(raw_lhs, raw_rhs);
  537. }
  538. template <class U1, class U2>
  539. bool operator==(U1* raw_lhs, const SmartPtr<U2>& rhs)
  540. {
  541. #ifdef IP_DEBUG_SMARTPTR
  542. DBG_START_FUN(
  543. "bool operator==(U1* raw_lhs, SmartPtr<U2>& rhs)",
  544. ipopt_dbg_smartptr_verbosity);
  545. #endif
  546. const U2* raw_rhs = GetRawPtr(rhs);
  547. return ComparePointers(raw_lhs, raw_rhs);
  548. }
  549. template <class U1, class U2>
  550. bool operator!=(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs)
  551. {
  552. #ifdef IP_DEBUG_SMARTPTR
  553. DBG_START_FUN(
  554. "bool operator!=(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs)",
  555. ipopt_dbg_smartptr_verbosity);
  556. #endif
  557. bool retValue = operator==(lhs, rhs);
  558. return !retValue;
  559. }
  560. template <class U1, class U2>
  561. bool operator!=(const SmartPtr<U1>& lhs, U2* raw_rhs)
  562. {
  563. #ifdef IP_DEBUG_SMARTPTR
  564. DBG_START_FUN(
  565. "bool operator!=(SmartPtr<U1>& lhs, U2* rhs)",
  566. ipopt_dbg_smartptr_verbosity);
  567. #endif
  568. bool retValue = operator==(lhs, raw_rhs);
  569. return !retValue;
  570. }
  571. template <class U1, class U2>
  572. bool operator!=(U1* raw_lhs, const SmartPtr<U2>& rhs)
  573. {
  574. #ifdef IP_DEBUG_SMARTPTR
  575. DBG_START_FUN(
  576. "bool operator!=(U1* raw_lhs, SmartPtr<U2>& rhs)",
  577. ipopt_dbg_smartptr_verbosity);
  578. #endif
  579. bool retValue = operator==(raw_lhs, rhs);
  580. return !retValue;
  581. }
  582. template <class T>
  583. void swap(SmartPtr<T>& a, SmartPtr<T>& b)
  584. {
  585. #ifdef IP_DEBUG_REFERENCED
  586. SmartPtr<T> tmp(a);
  587. a = b;
  588. b = tmp;
  589. #else
  590. std::swap(a.prt_, b.ptr_);
  591. #endif
  592. }
  593. template <class T>
  594. bool operator<(const SmartPtr<T>& lhs, const SmartPtr<T>& rhs)
  595. {
  596. return lhs.ptr_ < rhs.ptr_;
  597. }
  598. template <class T>
  599. bool operator> (const SmartPtr<T>& lhs, const SmartPtr<T>& rhs)
  600. {
  601. return rhs < lhs;
  602. }
  603. template <class T> bool
  604. operator<=(const SmartPtr<T>& lhs, const SmartPtr<T>& rhs)
  605. {
  606. return !( rhs < lhs );
  607. }
  608. template <class T> bool
  609. operator>=(const SmartPtr<T>& lhs, const SmartPtr<T>& rhs)
  610. {
  611. return !( lhs < rhs );
  612. }
  613. } // namespace Ipopt
  614. #undef ipopt_dbg_smartptr_verbosity
  615. #endif