You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							734 lines
						
					
					
						
							21 KiB
						
					
					
				
			
		
		
	
	
							734 lines
						
					
					
						
							21 KiB
						
					
					
				// Copyright (C) 2004, 2011 International Business Machines and others.
 | 
						|
// All Rights Reserved.
 | 
						|
// This code is published under the Eclipse Public License.
 | 
						|
//
 | 
						|
// $Id: IpSmartPtr.hpp 2182 2013-03-30 20:02:18Z stefan $
 | 
						|
//
 | 
						|
// Authors:  Carl Laird, Andreas Waechter     IBM    2004-08-13
 | 
						|
 | 
						|
#ifndef __IPSMARTPTR_HPP__
 | 
						|
#define __IPSMARTPTR_HPP__
 | 
						|
 | 
						|
#include "IpReferenced.hpp"
 | 
						|
 | 
						|
#include "IpDebug.hpp"
 | 
						|
#if COIN_IPOPT_CHECKLEVEL > 2
 | 
						|
# define IP_DEBUG_SMARTPTR
 | 
						|
#endif
 | 
						|
#ifndef IPOPT_UNUSED
 | 
						|
# if defined(__GNUC__)
 | 
						|
#   define IPOPT_UNUSED __attribute__((unused))
 | 
						|
# else
 | 
						|
#   define IPOPT_UNUSED
 | 
						|
# endif
 | 
						|
#endif
 | 
						|
 | 
						|
namespace Ipopt
 | 
						|
{
 | 
						|
 | 
						|
  /** Template class for Smart Pointers.
 | 
						|
   * A SmartPtr behaves much like a raw pointer, but manages the lifetime 
 | 
						|
   * of an object, deleting the object automatically. This class implements
 | 
						|
   * a reference-counting, intrusive smart pointer design, where all
 | 
						|
   * objects pointed to must inherit off of ReferencedObject, which
 | 
						|
   * stores the reference count. Although this is intrusive (native types
 | 
						|
   * and externally authored classes require wrappers to be referenced
 | 
						|
   * by smart pointers), it is a safer design. A more detailed discussion of
 | 
						|
   * these issues follows after the usage information.
 | 
						|
   * 
 | 
						|
   * Usage Example:
 | 
						|
   * Note: to use the SmartPtr, all objects to which you point MUST
 | 
						|
   * inherit off of ReferencedObject.
 | 
						|
   * 
 | 
						|
   * \verbatim
 | 
						|
   * 
 | 
						|
   * In MyClass.hpp...
 | 
						|
   * 
 | 
						|
   * #include "IpReferenced.hpp"
 | 
						|
 | 
						|
   * namespace Ipopt {
 | 
						|
   * 
 | 
						|
   *  class MyClass : public ReferencedObject // must derive from ReferencedObject
 | 
						|
   *    {
 | 
						|
   *      ...
 | 
						|
   *    }
 | 
						|
   * } // namespace Ipopt
 | 
						|
   * 
 | 
						|
   * 
 | 
						|
   * In my_usage.cpp...
 | 
						|
   * 
 | 
						|
   * #include "IpSmartPtr.hpp"
 | 
						|
   * #include "MyClass.hpp"
 | 
						|
   * 
 | 
						|
   * void func(AnyObject& obj)
 | 
						|
   *  {
 | 
						|
   *    SmartPtr<MyClass> ptr_to_myclass = new MyClass(...);
 | 
						|
   *    // ptr_to_myclass now points to a new MyClass,
 | 
						|
   *    // and the reference count is 1
 | 
						|
   *  
 | 
						|
   *    ...
 | 
						|
   * 
 | 
						|
   *    obj.SetMyClass(ptr_to_myclass);
 | 
						|
   *    // Here, let's assume that AnyObject uses a
 | 
						|
   *    // SmartPtr<MyClass> internally here.
 | 
						|
   *    // Now, both ptr_to_myclass and the internal
 | 
						|
   *    // SmartPtr in obj point to the same MyClass object
 | 
						|
   *    // and its reference count is 2.
 | 
						|
   * 
 | 
						|
   *    ...
 | 
						|
   * 
 | 
						|
   *    // No need to delete ptr_to_myclass, this
 | 
						|
   *    // will be done automatically when the
 | 
						|
   *    // reference count drops to zero.
 | 
						|
   * 
 | 
						|
   *  }  
 | 
						|
   *  
 | 
						|
   * \endverbatim
 | 
						|
   *
 | 
						|
   * It is not necessary to use SmartPtr's in all cases where an
 | 
						|
   * object is used that has been allocated "into" a SmartPtr.  It is
 | 
						|
   * possible to just pass objects by reference or regular pointers,
 | 
						|
   * even if lower down in the stack a SmartPtr is to be held on to.
 | 
						|
   * Everything should work fine as long as a pointer created by "new"
 | 
						|
   * is immediately passed into a SmartPtr, and if SmartPtr's are used
 | 
						|
   * to hold on to objects.
 | 
						|
   *
 | 
						|
   * Other Notes:
 | 
						|
   *  The SmartPtr implements both dereference operators -> & *.
 | 
						|
   *  The SmartPtr does NOT implement a conversion operator to
 | 
						|
   *    the raw pointer. Use the GetRawPtr() method when this
 | 
						|
   *    is necessary. Make sure that the raw pointer is NOT
 | 
						|
   *    deleted. 
 | 
						|
   *  The SmartPtr implements the comparison operators == & !=
 | 
						|
   *    for a variety of types. Use these instead of
 | 
						|
   *    \verbatim
 | 
						|
   *    if (GetRawPtr(smrt_ptr) == ptr) // Don't use this
 | 
						|
   *    \endverbatim
 | 
						|
   * SmartPtr's, as currently implemented, do NOT handle circular references.
 | 
						|
   *    For example: consider a higher level object using SmartPtrs to point to 
 | 
						|
   *    A and B, but A and B also point to each other (i.e. A has a SmartPtr 
 | 
						|
   *    to B and B has a SmartPtr to A). In this scenario, when the higher
 | 
						|
   *    level object is finished with A and B, their reference counts will 
 | 
						|
   *    never drop to zero (since they reference each other) and they
 | 
						|
   *    will not be deleted. This can be detected by memory leak tools like
 | 
						|
   *    valgrind. If the circular reference is necessary, the problem can be
 | 
						|
   *    overcome by a number of techniques:
 | 
						|
   *  
 | 
						|
   *    1) A and B can have a method that "releases" each other, that is
 | 
						|
   *        they set their internal SmartPtrs to NULL.
 | 
						|
   *        \verbatim
 | 
						|
   *        void AClass::ReleaseCircularReferences()
 | 
						|
   *          {
 | 
						|
   *          smart_ptr_to_B = NULL;
 | 
						|
   *          }
 | 
						|
   *        \endverbatim
 | 
						|
   *        Then, the higher level class can call these methods before
 | 
						|
   *        it is done using A & B.
 | 
						|
   * 
 | 
						|
   *    2) Raw pointers can be used in A and B to reference each other.
 | 
						|
   *        Here, an implicit assumption is made that the lifetime is
 | 
						|
   *        controlled by the higher level object and that A and B will
 | 
						|
   *        both exist in a controlled manner. Although this seems 
 | 
						|
   *        dangerous, in many situations, this type of referencing
 | 
						|
   *        is very controlled and this is reasonably safe.
 | 
						|
   * 
 | 
						|
   *    3) This SmartPtr class could be redesigned with the Weak/Strong
 | 
						|
   *        design concept. Here, the SmartPtr is identified as being
 | 
						|
   *        Strong (controls lifetime of the object) or Weak (merely
 | 
						|
   *        referencing the object). The Strong SmartPtr increments 
 | 
						|
   *        (and decrements) the reference count in ReferencedObject
 | 
						|
   *        but the Weak SmartPtr does not. In the example above,
 | 
						|
   *        the higher level object would have Strong SmartPtrs to
 | 
						|
   *        A and B, but A and B would have Weak SmartPtrs to each
 | 
						|
   *        other. Then, when the higher level object was done with
 | 
						|
   *        A and B, they would be deleted. The Weak SmartPtrs in A
 | 
						|
   *        and B would not decrement the reference count and would,
 | 
						|
   *        of course, not delete the object. This idea is very similar
 | 
						|
   *        to item (2), where it is implied that the sequence of events 
 | 
						|
   *        is controlled such that A and B will not call anything using
 | 
						|
   *        their pointers following the higher level delete (i.e. in
 | 
						|
   *        their destructors!). This is somehow safer, however, because
 | 
						|
   *        code can be written (however expensive) to perform run-time 
 | 
						|
   *        detection of this situation. For example, the ReferencedObject
 | 
						|
   *        could store pointers to all Weak SmartPtrs that are referencing
 | 
						|
   *        it and, in its destructor, tell these pointers that it is
 | 
						|
   *        dying. They could then set themselves to NULL, or set an
 | 
						|
   *        internal flag to detect usage past this point.
 | 
						|
   * 
 | 
						|
   * Comments on Non-Intrusive Design:
 | 
						|
   * In a non-intrusive design, the reference count is stored somewhere other
 | 
						|
   * than the object being referenced. This means, unless the reference
 | 
						|
   * counting pointer is the first referencer, it must get a pointer to the 
 | 
						|
   * referenced object from another smart pointer (so it has access to the 
 | 
						|
   * reference count location). In this non-intrusive design, if we are 
 | 
						|
   * pointing to an object with a smart pointer (or a number of smart
 | 
						|
   * pointers), and we then give another smart pointer the address through
 | 
						|
   * a RAW pointer, we will have two independent, AND INCORRECT, reference
 | 
						|
   * counts. To avoid this pitfall, we use an intrusive reference counting
 | 
						|
   * technique where the reference count is stored in the object being
 | 
						|
   * referenced. 
 | 
						|
   */
 | 
						|
  template<class T>
 | 
						|
  class SmartPtr : public Referencer
 | 
						|
  {
 | 
						|
  public:
 | 
						|
#define ipopt_dbg_smartptr_verbosity 0
 | 
						|
 | 
						|
    /**@name Constructors/Destructors */
 | 
						|
    //@{
 | 
						|
    /** Default constructor, initialized to NULL */
 | 
						|
    SmartPtr();
 | 
						|
 | 
						|
    /** Copy constructor, initialized from copy of type T */
 | 
						|
    SmartPtr(const SmartPtr<T>& copy);
 | 
						|
 | 
						|
    /** Copy constructor, initialized from copy of type U */
 | 
						|
    template <class U>
 | 
						|
    SmartPtr(const SmartPtr<U>& copy);
 | 
						|
 | 
						|
    /** Constructor, initialized from T* ptr */
 | 
						|
    SmartPtr(T* ptr);
 | 
						|
 | 
						|
    /** Destructor, automatically decrements the
 | 
						|
     * reference count, deletes the object if
 | 
						|
     * necessary.*/
 | 
						|
    ~SmartPtr();
 | 
						|
    //@}
 | 
						|
 | 
						|
    /**@name Overloaded operators. */
 | 
						|
    //@{
 | 
						|
    /** Overloaded arrow operator, allows the user to call
 | 
						|
     * methods using the contained pointer. */
 | 
						|
    T* operator->() const;
 | 
						|
 | 
						|
    /** Overloaded dereference operator, allows the user
 | 
						|
     * to dereference the contained pointer. */
 | 
						|
    T& operator*() const;
 | 
						|
 | 
						|
    /** Overloaded equals operator, allows the user to
 | 
						|
     * set the value of the SmartPtr from a raw pointer */
 | 
						|
    SmartPtr<T>& operator=(T* rhs);
 | 
						|
 | 
						|
    /** Overloaded equals operator, allows the user to
 | 
						|
     * set the value of the SmartPtr from another 
 | 
						|
     * SmartPtr */
 | 
						|
    SmartPtr<T>& operator=(const SmartPtr<T>& rhs);
 | 
						|
 | 
						|
    /** Overloaded equals operator, allows the user to
 | 
						|
     * set the value of the SmartPtr from another
 | 
						|
     * SmartPtr of a different type */
 | 
						|
    template <class U>
 | 
						|
    SmartPtr<T>& operator=(const SmartPtr<U>& rhs);
 | 
						|
 | 
						|
    /** Overloaded equality comparison operator, allows the
 | 
						|
     * user to compare the value of two SmartPtrs */
 | 
						|
    template <class U1, class U2>
 | 
						|
    friend
 | 
						|
    bool operator==(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs);
 | 
						|
 | 
						|
    /** Overloaded equality comparison operator, allows the
 | 
						|
     * user to compare the value of a SmartPtr with a raw pointer. */
 | 
						|
    template <class U1, class U2>
 | 
						|
    friend
 | 
						|
    bool operator==(const SmartPtr<U1>& lhs, U2* raw_rhs);
 | 
						|
 | 
						|
    /** Overloaded equality comparison operator, allows the
 | 
						|
     * user to compare the value of a raw pointer with a SmartPtr. */
 | 
						|
    template <class U1, class U2>
 | 
						|
    friend
 | 
						|
    bool operator==(U1* lhs, const SmartPtr<U2>& raw_rhs);
 | 
						|
 | 
						|
    /** Overloaded in-equality comparison operator, allows the
 | 
						|
     * user to compare the value of two SmartPtrs */
 | 
						|
    template <class U1, class U2>
 | 
						|
    friend
 | 
						|
    bool operator!=(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs);
 | 
						|
 | 
						|
    /** Overloaded in-equality comparison operator, allows the
 | 
						|
     * user to compare the value of a SmartPtr with a raw pointer. */
 | 
						|
    template <class U1, class U2>
 | 
						|
    friend
 | 
						|
    bool operator!=(const SmartPtr<U1>& lhs, U2* raw_rhs);
 | 
						|
 | 
						|
    /** Overloaded in-equality comparison operator, allows the
 | 
						|
     * user to compare the value of a SmartPtr with a raw pointer. */
 | 
						|
    template <class U1, class U2>
 | 
						|
    friend
 | 
						|
    bool operator!=(U1* lhs, const SmartPtr<U2>& raw_rhs);
 | 
						|
 | 
						|
    /** Overloaded less-than comparison operator, allows the
 | 
						|
     * user to compare the value of two SmartPtrs */
 | 
						|
    template <class U>
 | 
						|
    friend
 | 
						|
    bool operator<(const SmartPtr<U>& lhs, const SmartPtr<U>& rhs);
 | 
						|
    //@}
 | 
						|
 | 
						|
    /**@name friend method declarations. */
 | 
						|
    //@{
 | 
						|
    /** Returns the raw pointer contained.
 | 
						|
     * Use to get the value of
 | 
						|
     * the raw ptr (i.e. to pass to other
 | 
						|
     * methods/functions, etc.)
 | 
						|
     * Note: This method does NOT copy, 
 | 
						|
     * therefore, modifications using this
 | 
						|
     * value modify the underlying object 
 | 
						|
     * contained by the SmartPtr,
 | 
						|
     * NEVER delete this returned value.
 | 
						|
     */
 | 
						|
    template <class U>
 | 
						|
    friend
 | 
						|
    U* GetRawPtr(const SmartPtr<U>& smart_ptr);
 | 
						|
 | 
						|
    /** Returns a const pointer */
 | 
						|
    template <class U>
 | 
						|
    friend
 | 
						|
    SmartPtr<const U> ConstPtr(const SmartPtr<U>& smart_ptr);
 | 
						|
 | 
						|
    /** Returns true if the SmartPtr is NOT NULL.
 | 
						|
     * Use this to check if the SmartPtr is not null
 | 
						|
     * This is preferred to if(GetRawPtr(sp) != NULL)
 | 
						|
     */
 | 
						|
    template <class U>
 | 
						|
    friend
 | 
						|
    bool IsValid(const SmartPtr<U>& smart_ptr);
 | 
						|
 | 
						|
    /** Returns true if the SmartPtr is NULL.
 | 
						|
     * Use this to check if the SmartPtr IsNull.
 | 
						|
     * This is preferred to if(GetRawPtr(sp) == NULL)
 | 
						|
     */
 | 
						|
    template <class U>
 | 
						|
    friend
 | 
						|
    bool IsNull(const SmartPtr<U>& smart_ptr);
 | 
						|
    //@}
 | 
						|
 | 
						|
  private:
 | 
						|
    /**@name Private Data/Methods */
 | 
						|
    //@{
 | 
						|
    /** Actual raw pointer to the object. */
 | 
						|
    T* ptr_;
 | 
						|
 | 
						|
    /** Set the value of the internal raw pointer
 | 
						|
     * from another raw pointer, releasing the 
 | 
						|
     * previously referenced object if necessary. */
 | 
						|
    SmartPtr<T>& SetFromRawPtr_(T* rhs);
 | 
						|
 | 
						|
    /** Set the value of the internal raw pointer
 | 
						|
     * from a SmartPtr, releasing the previously referenced
 | 
						|
     * object if necessary. */
 | 
						|
    SmartPtr<T>& SetFromSmartPtr_(const SmartPtr<T>& rhs);
 | 
						|
 | 
						|
    /** Release the currently referenced object. */
 | 
						|
    void ReleasePointer_();
 | 
						|
    //@}
 | 
						|
  };
 | 
						|
 | 
						|
  /**@name SmartPtr friend function declarations.*/
 | 
						|
  //@{
 | 
						|
  template <class U>
 | 
						|
  U* GetRawPtr(const SmartPtr<U>& smart_ptr);
 | 
						|
 | 
						|
  template <class U>
 | 
						|
  SmartPtr<const U> ConstPtr(const SmartPtr<U>& smart_ptr);
 | 
						|
 | 
						|
  template <class U>
 | 
						|
  bool IsNull(const SmartPtr<U>& smart_ptr);
 | 
						|
 | 
						|
  template <class U>
 | 
						|
  bool IsValid(const SmartPtr<U>& smart_ptr);
 | 
						|
 | 
						|
  template <class U1, class U2>
 | 
						|
  bool operator==(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs);
 | 
						|
 | 
						|
  template <class U1, class U2>
 | 
						|
  bool operator==(const SmartPtr<U1>& lhs, U2* raw_rhs);
 | 
						|
 | 
						|
  template <class U1, class U2>
 | 
						|
  bool operator==(U1* lhs, const SmartPtr<U2>& raw_rhs);
 | 
						|
 | 
						|
  template <class U1, class U2>
 | 
						|
  bool operator!=(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs);
 | 
						|
 | 
						|
  template <class U1, class U2>
 | 
						|
  bool operator!=(const SmartPtr<U1>& lhs, U2* raw_rhs);
 | 
						|
 | 
						|
  template <class U1, class U2>
 | 
						|
  bool operator!=(U1* lhs, const SmartPtr<U2>& raw_rhs);
 | 
						|
 | 
						|
  //@}
 | 
						|
 | 
						|
 | 
						|
  template <class T>
 | 
						|
  SmartPtr<T>::SmartPtr()
 | 
						|
      :
 | 
						|
      ptr_(0)
 | 
						|
  {
 | 
						|
#ifdef IP_DEBUG_SMARTPTR
 | 
						|
    DBG_START_METH("SmartPtr<T>::SmartPtr()", ipopt_dbg_smartptr_verbosity);
 | 
						|
#endif
 | 
						|
 | 
						|
#ifndef NDEBUG
 | 
						|
    const ReferencedObject* IPOPT_UNUSED trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_ = ptr_;
 | 
						|
#endif
 | 
						|
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  template <class T>
 | 
						|
  SmartPtr<T>::SmartPtr(const SmartPtr<T>& copy)
 | 
						|
      :
 | 
						|
      ptr_(0)
 | 
						|
  {
 | 
						|
#ifdef IP_DEBUG_SMARTPTR
 | 
						|
    DBG_START_METH("SmartPtr<T>::SmartPtr(const SmartPtr<T>& copy)", ipopt_dbg_smartptr_verbosity);
 | 
						|
#endif
 | 
						|
 | 
						|
#ifndef NDEBUG
 | 
						|
    const ReferencedObject* IPOPT_UNUSED trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_ = ptr_;
 | 
						|
#endif
 | 
						|
 | 
						|
    (void) SetFromSmartPtr_(copy);
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  template <class T>
 | 
						|
  template <class U>
 | 
						|
  SmartPtr<T>::SmartPtr(const SmartPtr<U>& copy)
 | 
						|
      :
 | 
						|
      ptr_(0)
 | 
						|
  {
 | 
						|
#ifdef IP_DEBUG_SMARTPTR
 | 
						|
    DBG_START_METH("SmartPtr<T>::SmartPtr(const SmartPtr<U>& copy)", ipopt_dbg_smartptr_verbosity);
 | 
						|
#endif
 | 
						|
 | 
						|
#ifndef NDEBUG
 | 
						|
    const ReferencedObject* IPOPT_UNUSED trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_ = ptr_;
 | 
						|
#endif
 | 
						|
 | 
						|
    (void) SetFromSmartPtr_(GetRawPtr(copy));
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  template <class T>
 | 
						|
  SmartPtr<T>::SmartPtr(T* ptr)
 | 
						|
      :
 | 
						|
      ptr_(0)
 | 
						|
  {
 | 
						|
#ifdef IP_DEBUG_SMARTPTR
 | 
						|
    DBG_START_METH("SmartPtr<T>::SmartPtr(T* ptr)", ipopt_dbg_smartptr_verbosity);
 | 
						|
#endif
 | 
						|
 | 
						|
#ifndef NDEBUG
 | 
						|
    const ReferencedObject* IPOPT_UNUSED trying_to_use_SmartPtr_with_an_object_that_does_not_inherit_from_ReferencedObject_ = ptr_;
 | 
						|
#endif
 | 
						|
 | 
						|
    (void) SetFromRawPtr_(ptr);
 | 
						|
  }
 | 
						|
 | 
						|
  template <class T>
 | 
						|
  SmartPtr<T>::~SmartPtr()
 | 
						|
  {
 | 
						|
#ifdef IP_DEBUG_SMARTPTR
 | 
						|
    DBG_START_METH("SmartPtr<T>::~SmartPtr(T* ptr)", ipopt_dbg_smartptr_verbosity);
 | 
						|
#endif
 | 
						|
 | 
						|
    ReleasePointer_();
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  template <class T>
 | 
						|
  T* SmartPtr<T>::operator->() const
 | 
						|
  {
 | 
						|
#ifdef IP_DEBUG_SMARTPTR
 | 
						|
    DBG_START_METH("T* SmartPtr<T>::operator->()", ipopt_dbg_smartptr_verbosity);
 | 
						|
#endif
 | 
						|
 | 
						|
    // cannot deref a null pointer
 | 
						|
#if COIN_IPOPT_CHECKLEVEL > 0
 | 
						|
    assert(ptr_);
 | 
						|
#endif
 | 
						|
 | 
						|
    return ptr_;
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  template <class T>
 | 
						|
  T& SmartPtr<T>::operator*() const
 | 
						|
  {
 | 
						|
#ifdef IP_DEBUG_SMARTPTR
 | 
						|
    DBG_START_METH("T& SmartPtr<T>::operator*()", ipopt_dbg_smartptr_verbosity);
 | 
						|
#endif
 | 
						|
 | 
						|
    // cannot dereference a null pointer
 | 
						|
#if COIN_IPOPT_CHECKLEVEL > 0
 | 
						|
    assert(ptr_);
 | 
						|
#endif
 | 
						|
 | 
						|
    return *ptr_;
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  template <class T>
 | 
						|
  SmartPtr<T>& SmartPtr<T>::operator=(T* rhs)
 | 
						|
  {
 | 
						|
#ifdef IP_DEBUG_SMARTPTR
 | 
						|
    DBG_START_METH("SmartPtr<T>& SmartPtr<T>::operator=(T* rhs)", ipopt_dbg_smartptr_verbosity);
 | 
						|
#endif
 | 
						|
 | 
						|
    return SetFromRawPtr_(rhs);
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  template <class T>
 | 
						|
  SmartPtr<T>& SmartPtr<T>::operator=(const SmartPtr<T>& rhs)
 | 
						|
  {
 | 
						|
#ifdef IP_DEBUG_SMARTPTR
 | 
						|
    DBG_START_METH(
 | 
						|
      "SmartPtr<T>& SmartPtr<T>::operator=(const SmartPtr<T>& rhs)",
 | 
						|
      ipopt_dbg_smartptr_verbosity);
 | 
						|
#endif
 | 
						|
 | 
						|
    return SetFromSmartPtr_(rhs);
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  template <class T>
 | 
						|
  template <class U>
 | 
						|
  SmartPtr<T>& SmartPtr<T>::operator=(const SmartPtr<U>& rhs)
 | 
						|
  {
 | 
						|
#ifdef IP_DEBUG_SMARTPTR
 | 
						|
    DBG_START_METH(
 | 
						|
      "SmartPtr<T>& SmartPtr<T>::operator=(const SmartPtr<U>& rhs)",
 | 
						|
      ipopt_dbg_smartptr_verbosity);
 | 
						|
#endif
 | 
						|
 | 
						|
    return SetFromSmartPtr_(GetRawPtr(rhs));
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  template <class T>
 | 
						|
  SmartPtr<T>& SmartPtr<T>::SetFromRawPtr_(T* rhs)
 | 
						|
  {
 | 
						|
#ifdef IP_DEBUG_SMARTPTR
 | 
						|
    DBG_START_METH(
 | 
						|
      "SmartPtr<T>& SmartPtr<T>::SetFromRawPtr_(T* rhs)", ipopt_dbg_smartptr_verbosity);
 | 
						|
#endif
 | 
						|
 | 
						|
    if (rhs != 0)
 | 
						|
      rhs->AddRef(this);
 | 
						|
 | 
						|
    // Release any old pointer
 | 
						|
    ReleasePointer_();
 | 
						|
 | 
						|
    ptr_ = rhs;
 | 
						|
 | 
						|
    return *this;
 | 
						|
  }
 | 
						|
 | 
						|
  template <class T>
 | 
						|
  SmartPtr<T>& SmartPtr<T>::SetFromSmartPtr_(const SmartPtr<T>& rhs)
 | 
						|
  {
 | 
						|
#ifdef IP_DEBUG_SMARTPTR
 | 
						|
    DBG_START_METH(
 | 
						|
      "SmartPtr<T>& SmartPtr<T>::SetFromSmartPtr_(const SmartPtr<T>& rhs)",
 | 
						|
      ipopt_dbg_smartptr_verbosity);
 | 
						|
#endif
 | 
						|
 | 
						|
    SetFromRawPtr_(GetRawPtr(rhs));
 | 
						|
 | 
						|
    return (*this);
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  template <class T>
 | 
						|
  void SmartPtr<T>::ReleasePointer_()
 | 
						|
  {
 | 
						|
#ifdef IP_DEBUG_SMARTPTR
 | 
						|
    DBG_START_METH(
 | 
						|
      "void SmartPtr<T>::ReleasePointer()",
 | 
						|
      ipopt_dbg_smartptr_verbosity);
 | 
						|
#endif
 | 
						|
 | 
						|
    if (ptr_) {
 | 
						|
      ptr_->ReleaseRef(this);
 | 
						|
      if (ptr_->ReferenceCount() == 0)
 | 
						|
        delete ptr_;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  template <class U>
 | 
						|
  U* GetRawPtr(const SmartPtr<U>& smart_ptr)
 | 
						|
  {
 | 
						|
#ifdef IP_DEBUG_SMARTPTR
 | 
						|
    DBG_START_FUN(
 | 
						|
      "T* GetRawPtr(const SmartPtr<T>& smart_ptr)",
 | 
						|
      0);
 | 
						|
#endif
 | 
						|
 | 
						|
    return smart_ptr.ptr_;
 | 
						|
  }
 | 
						|
 | 
						|
  template <class U>
 | 
						|
  SmartPtr<const U> ConstPtr(const SmartPtr<U>& smart_ptr)
 | 
						|
  {
 | 
						|
    // compiler should implicitly cast
 | 
						|
    return GetRawPtr(smart_ptr);
 | 
						|
  }
 | 
						|
 | 
						|
  template <class U>
 | 
						|
  bool IsValid(const SmartPtr<U>& smart_ptr)
 | 
						|
  {
 | 
						|
    return !IsNull(smart_ptr);
 | 
						|
  }
 | 
						|
 | 
						|
  template <class U>
 | 
						|
  bool IsNull(const SmartPtr<U>& smart_ptr)
 | 
						|
  {
 | 
						|
#ifdef IP_DEBUG_SMARTPTR
 | 
						|
    DBG_START_FUN(
 | 
						|
      "bool IsNull(const SmartPtr<T>& smart_ptr)",
 | 
						|
      0);
 | 
						|
#endif
 | 
						|
 | 
						|
    return (smart_ptr.ptr_ == 0);
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  template <class U1, class U2>
 | 
						|
  bool ComparePointers(const U1* lhs, const U2* rhs)
 | 
						|
  {
 | 
						|
#ifdef IP_DEBUG_SMARTPTR
 | 
						|
    DBG_START_FUN(
 | 
						|
      "bool ComparePtrs(const U1* lhs, const U2* rhs)",
 | 
						|
      ipopt_dbg_smartptr_verbosity);
 | 
						|
#endif
 | 
						|
 | 
						|
    // Even if lhs and rhs point to the same object
 | 
						|
    // with different interfaces U1 and U2, we cannot guarantee that
 | 
						|
    // the value of the pointers will be equivalent. We can
 | 
						|
    // guarantee this if we convert to ReferencedObject* (see also #162)
 | 
						|
    const ReferencedObject* v_lhs = lhs;
 | 
						|
    const ReferencedObject* v_rhs = rhs;
 | 
						|
 | 
						|
    return v_lhs == v_rhs;
 | 
						|
  }
 | 
						|
 | 
						|
  template <class U1, class U2>
 | 
						|
  bool operator==(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs)
 | 
						|
  {
 | 
						|
#ifdef IP_DEBUG_SMARTPTR
 | 
						|
    DBG_START_FUN(
 | 
						|
      "bool operator==(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs)",
 | 
						|
      ipopt_dbg_smartptr_verbosity);
 | 
						|
#endif
 | 
						|
 | 
						|
    U1* raw_lhs = GetRawPtr(lhs);
 | 
						|
    U2* raw_rhs = GetRawPtr(rhs);
 | 
						|
    return ComparePointers(raw_lhs, raw_rhs);
 | 
						|
  }
 | 
						|
 | 
						|
  template <class U1, class U2>
 | 
						|
  bool operator==(const SmartPtr<U1>& lhs, U2* raw_rhs)
 | 
						|
  {
 | 
						|
#ifdef IP_DEBUG_SMARTPTR
 | 
						|
    DBG_START_FUN(
 | 
						|
      "bool operator==(SmartPtr<U1>& lhs, U2* rhs)",
 | 
						|
      ipopt_dbg_smartptr_verbosity);
 | 
						|
#endif
 | 
						|
 | 
						|
    U1* raw_lhs = GetRawPtr(lhs);
 | 
						|
    return ComparePointers(raw_lhs, raw_rhs);
 | 
						|
  }
 | 
						|
 | 
						|
  template <class U1, class U2>
 | 
						|
  bool operator==(U1* raw_lhs, const SmartPtr<U2>& rhs)
 | 
						|
  {
 | 
						|
#ifdef IP_DEBUG_SMARTPTR
 | 
						|
    DBG_START_FUN(
 | 
						|
      "bool operator==(U1* raw_lhs, SmartPtr<U2>& rhs)",
 | 
						|
      ipopt_dbg_smartptr_verbosity);
 | 
						|
#endif
 | 
						|
 | 
						|
    const U2* raw_rhs = GetRawPtr(rhs);
 | 
						|
    return ComparePointers(raw_lhs, raw_rhs);
 | 
						|
  }
 | 
						|
 | 
						|
  template <class U1, class U2>
 | 
						|
  bool operator!=(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs)
 | 
						|
  {
 | 
						|
#ifdef IP_DEBUG_SMARTPTR
 | 
						|
    DBG_START_FUN(
 | 
						|
      "bool operator!=(const SmartPtr<U1>& lhs, const SmartPtr<U2>& rhs)",
 | 
						|
      ipopt_dbg_smartptr_verbosity);
 | 
						|
#endif
 | 
						|
 | 
						|
    bool retValue = operator==(lhs, rhs);
 | 
						|
    return !retValue;
 | 
						|
  }
 | 
						|
 | 
						|
  template <class U1, class U2>
 | 
						|
  bool operator!=(const SmartPtr<U1>& lhs, U2* raw_rhs)
 | 
						|
  {
 | 
						|
#ifdef IP_DEBUG_SMARTPTR
 | 
						|
    DBG_START_FUN(
 | 
						|
      "bool operator!=(SmartPtr<U1>& lhs, U2* rhs)",
 | 
						|
      ipopt_dbg_smartptr_verbosity);
 | 
						|
#endif
 | 
						|
 | 
						|
    bool retValue = operator==(lhs, raw_rhs);
 | 
						|
    return !retValue;
 | 
						|
  }
 | 
						|
 | 
						|
  template <class U1, class U2>
 | 
						|
  bool operator!=(U1* raw_lhs, const SmartPtr<U2>& rhs)
 | 
						|
  {
 | 
						|
#ifdef IP_DEBUG_SMARTPTR
 | 
						|
    DBG_START_FUN(
 | 
						|
      "bool operator!=(U1* raw_lhs, SmartPtr<U2>& rhs)",
 | 
						|
      ipopt_dbg_smartptr_verbosity);
 | 
						|
#endif
 | 
						|
 | 
						|
    bool retValue = operator==(raw_lhs, rhs);
 | 
						|
    return !retValue;
 | 
						|
  }
 | 
						|
 | 
						|
  template <class T>
 | 
						|
  void swap(SmartPtr<T>& a, SmartPtr<T>& b)
 | 
						|
  {
 | 
						|
#ifdef IP_DEBUG_REFERENCED
 | 
						|
    SmartPtr<T> tmp(a);
 | 
						|
    a = b;
 | 
						|
    b = tmp;
 | 
						|
#else
 | 
						|
    std::swap(a.prt_, b.ptr_);
 | 
						|
#endif
 | 
						|
  }
 | 
						|
 | 
						|
  template <class T>
 | 
						|
  bool operator<(const SmartPtr<T>& lhs, const SmartPtr<T>& rhs)
 | 
						|
  {
 | 
						|
    return lhs.ptr_ < rhs.ptr_;
 | 
						|
  }
 | 
						|
 | 
						|
  template <class T>
 | 
						|
  bool operator> (const SmartPtr<T>& lhs, const SmartPtr<T>& rhs)
 | 
						|
  {
 | 
						|
    return rhs < lhs;
 | 
						|
  }
 | 
						|
 | 
						|
  template <class T> bool
 | 
						|
  operator<=(const SmartPtr<T>& lhs, const SmartPtr<T>& rhs)
 | 
						|
  {
 | 
						|
    return !( rhs < lhs );
 | 
						|
  }
 | 
						|
 | 
						|
  template <class T> bool
 | 
						|
  operator>=(const SmartPtr<T>& lhs, const SmartPtr<T>& rhs)
 | 
						|
  {
 | 
						|
    return !( lhs < rhs );
 | 
						|
  }
 | 
						|
} // namespace Ipopt
 | 
						|
 | 
						|
#undef ipopt_dbg_smartptr_verbosity
 | 
						|
 | 
						|
#endif
 | 
						|
 |