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

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

adapted for Portland compilers

  • 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 567 2005-11-01 23:27:11Z 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#ifndef __PGI
356    const ReferencedObject* trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_
357    = ptr_;
358    trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_ = NULL;
359#endif
360
361  }
362
363
364  template <class T>
365  SmartPtr<T>::SmartPtr(const SmartPtr<T>& copy)
366      :
367      ptr_(NULL)
368  {
369#ifdef IP_DEBUG_SMARTPTR
370    DBG_START_METH("SmartPtr<T>::SmartPtr(const SmartPtr<T>& copy)", dbg_smartptr_verbosity);
371#endif
372
373#ifndef __PGI
374    const ReferencedObject* trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_
375    = ptr_;
376    trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_ = NULL;
377#endif
378
379    (void) SetFromSmartPtr_(copy);
380  }
381
382
383  /* Don't support this, use dynamic_cast(GetRawPtr(copy))
384  template <class T>
385  template <class U> SmartPtr<T>::SmartPtr(const SmartPtr<U>& copy)
386   :
387   ptr_(NULL)
388   {
389     DBG_START_METH("SmartPtr<T>::SmartPtr(const SmartPtr<U>& copy)", dbg_smartptr_verbosity);
390     
391     U* raw_U_ptr = GetRawPtr(copy);
392     
393     // try to cast to type T
394     T* raw_T_ptr = dynamic_cast<T*>(raw_U_ptr);
395     
396     // Don't try to point to type U with a
397     // type T SmartPtr if the types U & T
398     // are not related
399     DBG_ASSERT(raw_T_ptr);
400     
401     (void) SetFromRawPtr_(raw_T_ptr);
402   }
403   */
404
405
406  template <class T>
407  SmartPtr<T>::SmartPtr(T* ptr)
408      :
409      ptr_(NULL)
410  {
411#ifdef IP_DEBUG_SMARTPTR
412    DBG_START_METH("SmartPtr<T>::SmartPtr(T* ptr)", dbg_smartptr_verbosity);
413#endif
414
415#ifndef __PGI
416    const ReferencedObject* trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_
417    = ptr_;
418    trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_ = NULL;
419#endif
420
421    (void) SetFromRawPtr_(ptr);
422  }
423
424  template <class T>
425  SmartPtr<T>::~SmartPtr()
426  {
427#ifdef IP_DEBUG_SMARTPTR
428    DBG_START_METH("SmartPtr<T>::~SmartPtr(T* ptr)", dbg_smartptr_verbosity);
429#endif
430
431    ReleasePointer_();
432  }
433
434
435  template <class T>
436  T* SmartPtr<T>::operator->() const
437  {
438#ifdef IP_DEBUG_SMARTPTR
439    DBG_START_METH("T* SmartPtr<T>::operator->()", dbg_smartptr_verbosity);
440#endif
441
442    // cannot deref a null pointer
443#ifdef IP_DEBUG
444
445    assert(ptr_);
446#endif
447
448    return ptr_;
449  }
450
451
452  template <class T>
453  T& SmartPtr<T>::operator*() const
454  {
455#ifdef IP_DEBUG_SMARTPTR
456    DBG_START_METH("T& SmartPtr<T>::operator*()", dbg_smartptr_verbosity);
457#endif
458
459    // cannot dereference a null pointer
460#ifdef IP_DEBUG
461
462    assert(ptr_);
463#endif
464
465    return *ptr_;
466  }
467
468
469  template <class T>
470  SmartPtr<T>& SmartPtr<T>::operator=(T* rhs)
471  {
472#ifdef IP_DEBUG_SMARTPTR
473    DBG_START_METH("SmartPtr<T>& SmartPtr<T>::operator=(T* rhs)", dbg_smartptr_verbosity);
474#endif
475
476    return SetFromRawPtr_(rhs);
477  }
478
479
480  template <class T>
481  SmartPtr<T>& SmartPtr<T>::operator=(const SmartPtr<T>& rhs)
482  {
483#ifdef IP_DEBUG_SMARTPTR
484    DBG_START_METH(
485      "SmartPtr<T>& SmartPtr<T>::operator=(const SmartPtr<T>& rhs)",
486      dbg_smartptr_verbosity);
487#endif
488
489    return SetFromSmartPtr_(rhs);
490  }
491
492
493  template <class T>
494  SmartPtr<T>& SmartPtr<T>::SetFromRawPtr_(T* rhs)
495  {
496#ifdef IP_DEBUG_SMARTPTR
497    DBG_START_METH(
498      "SmartPtr<T>& SmartPtr<T>::SetFromRawPtr_(T* rhs)", dbg_smartptr_verbosity);
499#endif
500
501    // Release any old pointer
502    ReleasePointer_();
503
504    if (rhs != NULL) {
505      rhs->AddRef(this);
506      ptr_ = rhs;
507      //       const ReferencedObject* r_ptr =
508      //         dynamic_cast<const ReferencedObject*>(rhs);
509
510      //       // All objects pointed to by a SmartPtr MUST
511      //       // inherit off of ReferencedObject
512      //       DBG_ASSERT(r_ptr && "This is not inherited from ReferencedObject");
513
514      //       if (r_ptr) {
515      //         r_ptr->AddRef(this);
516      //         ptr_ = rhs;
517      //       }
518    }
519
520    return *this;
521  }
522
523  template <class T>
524  SmartPtr<T>& SmartPtr<T>::SetFromSmartPtr_(const SmartPtr<T>& rhs)
525  {
526#ifdef IP_DEBUG_SMARTPTR
527    DBG_START_METH(
528      "SmartPtr<T>& SmartPtr<T>::SetFromSmartPtr_(const SmartPtr<T>& rhs)",
529      dbg_smartptr_verbosity);
530#endif
531
532    T* ptr = GetRawPtr(rhs);
533    if (ptr != NULL) {
534      SetFromRawPtr_(ptr);
535    }
536
537    return (*this);
538  }
539
540
541  template <class T>
542  void SmartPtr<T>::ReleasePointer_()
543  {
544#ifdef IP_DEBUG_SMARTPTR
545    DBG_START_METH(
546      "void SmartPtr<T>::ReleasePointer()",
547      dbg_smartptr_verbosity);
548#endif
549
550    if (ptr_) {
551      ptr_->ReleaseRef(this);
552      if (ptr_->ReferenceCount() == 0) {
553        delete ptr_;
554      }
555      ptr_ = NULL;
556    }
557    //     if (ptr_ != NULL) {
558    //       const ReferencedObject* r_ptr =
559    //         dynamic_cast<const ReferencedObject*>(ptr_);
560
561    //       r_ptr->ReleaseRef(this);
562    //       if (r_ptr->ReferenceCount() == 0) {
563    //         delete ptr_;
564    //       }
565    //       ptr_ = NULL;
566    //     }
567  }
568
569
570  template <class U>
571  U* GetRawPtr(const SmartPtr<U>& smart_ptr)
572  {
573#ifdef IP_DEBUG_SMARTPTR
574    DBG_START_FUN(
575      "T* GetRawPtr(const SmartPtr<T>& smart_ptr)",
576      0);
577#endif
578
579    return smart_ptr.ptr_;
580  }
581
582  template <class U>
583  SmartPtr<const U> ConstPtr(const SmartPtr<U>& smart_ptr)
584  {
585    // compiler should implicitly cast
586    return GetRawPtr(smart_ptr);
587  }
588
589  template <class U>
590  bool IsValid(const SmartPtr<U>& smart_ptr)
591  {
592    return !IsNull(smart_ptr);
593  }
594
595  template <class U>
596  bool IsNull(const SmartPtr<U>& smart_ptr)
597  {
598#ifdef IP_DEBUG_SMARTPTR
599    DBG_START_FUN(
600      "bool IsNull(const SmartPtr<T>& smart_ptr)",
601      0);
602#endif
603
604    return (smart_ptr.ptr_ == NULL);
605  }
606
607
608  template <class U1, class U2>
609  bool ComparePointers(const U1* lhs, const U2* rhs)
610  {
611#ifdef IP_DEBUG_SMARTPTR
612    DBG_START_FUN(
613      "bool ComparePtrs(const U1* lhs, const U2* rhs)",
614      dbg_smartptr_verbosity);
615#endif
616
617    if (lhs == rhs) {
618      return true;
619    }
620
621    // Even if lhs and rhs point to the same object
622    // with different interfaces U1 and U2, we cannot guarantee that
623    // the value of the pointers will be equivalent. We can
624    // guarantee this if we convert to void*
625    const void* v_lhs = dynamic_cast<const void*>(lhs);
626    const void* v_rhs = dynamic_cast<const void*>(rhs);
627    if (v_lhs == v_rhs) {
628      return true;
629    }
630
631    // They must not be the same
632    return false;
633  }
634
635  template <class U1, class U2>
636  bool operator==(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs)
637  {
638#ifdef IP_DEBUG_SMARTPTR
639    DBG_START_FUN(
640      "bool operator==(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs)",
641      dbg_smartptr_verbosity);
642#endif
643
644    U1* raw_lhs = GetRawPtr(lhs);
645    U2* raw_rhs = GetRawPtr(rhs);
646    return ComparePointers(raw_lhs, raw_rhs);
647  }
648
649  template <class U1, class U2>
650  bool operator==(const SmartPtr<U1>& lhs, U2* raw_rhs)
651  {
652#ifdef IP_DEBUG_SMARTPTR
653    DBG_START_FUN(
654      "bool operator==(SmartPtr<U1>& lhs, U2* rhs)",
655      dbg_smartptr_verbosity);
656#endif
657
658    U1* raw_lhs = GetRawPtr(lhs);
659    return ComparePointers(raw_lhs, raw_rhs);
660  }
661
662  template <class U1, class U2>
663  bool operator==(U1* raw_lhs, const SmartPtr<U2>& rhs)
664  {
665#ifdef IP_DEBUG_SMARTPTR
666    DBG_START_FUN(
667      "bool operator==(U1* raw_lhs, SmartPtr<U2>& rhs)",
668      dbg_smartptr_verbosity);
669#endif
670
671    const U2* raw_rhs = GetRawPtr(rhs);
672    return ComparePointers(raw_lhs, raw_rhs);
673  }
674
675  template <class U1, class U2>
676  bool operator!=(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs)
677  {
678#ifdef IP_DEBUG_SMARTPTR
679    DBG_START_FUN(
680      "bool operator!=(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs)",
681      dbg_smartptr_verbosity);
682#endif
683
684    bool retValue = operator==(lhs, rhs);
685    return !retValue;
686  }
687
688  template <class U1, class U2>
689  bool operator!=(const SmartPtr<U1>& lhs, U2* raw_rhs)
690  {
691#ifdef IP_DEBUG_SMARTPTR
692    DBG_START_FUN(
693      "bool operator!=(SmartPtr<U1>& lhs, U2* rhs)",
694      dbg_smartptr_verbosity);
695#endif
696
697    bool retValue = operator==(lhs, raw_rhs);
698    return !retValue;
699  }
700
701  template <class U1, class U2>
702  bool operator!=(U1* raw_lhs, const SmartPtr<U2>& rhs)
703  {
704#ifdef IP_DEBUG_SMARTPTR
705    DBG_START_FUN(
706      "bool operator!=(U1* raw_lhs, SmartPtr<U2>& rhs)",
707      dbg_smartptr_verbosity);
708#endif
709
710    bool retValue = operator==(raw_lhs, rhs);
711    return !retValue;
712  }
713
714} // namespace Ipopt
715
716#endif
717
Note: See TracBrowser for help on using the repository browser.