source: branches/dev/Common/IpSmartPtr.hpp @ 510

Last change on this file since 510 was 510, checked in by andreasw, 15 years ago

final touches to release as first official version 3.0.0 (to be copied to trunk)

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