A Sample auto_ptr implementation

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Ankur Arora

    #1

    A Sample auto_ptr implementation

    Hi All,

    I'm building a sample application that uses a custom auto_ptr
    implementation.
    The program crashes with the following output:-

    Output (Debug Assertion failed)
    ----------


    release called
    copy constructor
    aap: ptr2= 10
    aap: ptr3= 20
    aap: ptr3= 10
    aap: exiting app
    Deleting pointee...10
    Deleting pointee...-572662307 (...problem ?)

    Code
    --------

    #include<iostre am>

    using namespace std;

    // MyAutoPtr Interface
    template <class T>
    class MyAutoPtr
    {
    public:

    explicit MyAutoPtr(T* ptr=0);

    ~MyAutoPtr();

    template <class U>
    MyAutoPtr(MyAut oPtr<U*rhs);

    //copy constructor member template, initialize this member pointer
    with any other compatible auto_ptr
    template <class U>
    MyAutoPtr(MyAut oPtr<U>& rhs);

    //assignment operator
    template <class U>
    MyAutoPtr<T>& operator=(MyAut oPtr<U>& rhs);

    //relinquish ownership
    T* release();

    T* get() const;

    //reset the auto_ptr, delete pointee, assume ownership of p
    void reset(T* ptr=0);

    T& operator*() const;
    T* operator->() const;


    private:

    T* pointee;
    //template <class U>
    //friend class MyAutoPtr<U>;
    };

    //Implementation

    template<typena me T>
    inline MyAutoPtr<T>::M yAutoPtr(T* ptr):pointee(pt r)
    { }

    template <class T>
    inline MyAutoPtr<T>::~ MyAutoPtr()
    {
    if(pointee)
    {
    cout<<"\n\t Deleting pointee..."<<*p ointee;
    delete pointee;
    }
    }

    template <class T>
    template <class U>
    inline MyAutoPtr<T>::M yAutoPtr(MyAuto Ptr<U>& rhs) :
    pointee(rhs.rel ease())
    {
    cout<<"\n\t copy constructor";
    }

    template<class T>
    template<class U>
    MyAutoPtr<T>& MyAutoPtr<T>::o perator=(MyAuto Ptr<U>& rhs)
    {
    cout<<"\n\t Inside operator=";
    if(this!=&rhs)
    {
    cout<<"\n\t Inside operator=, calling reset";
    reset(rhs.relea se());
    }
    return *this;
    }

    template <class T>
    T* MyAutoPtr<T>::g et() const
    {
    return pointee;
    }

    template <class T>
    inline T& MyAutoPtr<T>::o perator *() const
    {
    return *pointee;
    }

    template<class T>
    inline T* MyAutoPtr<T>::o perator->() const
    { return pointee; }

    template<class T>
    T* MyAutoPtr<T>::r elease()
    {
    cout<<"\n\t release called";
    T* oldp=pointee;
    pointee=0;

    return oldp;
    }

    template<class T>
    void MyAutoPtr<T>::r eset(T* p)
    {
    cout<<"\n\t reset called";
    if(pointee!=p)
    {
    delete pointee;
    //pointee=0;
    }

    pointee=p;
    }

    void main()
    {
    MyAutoPtr<intin tp(new int(10));
    MyAutoPtr<intin tp2(intp);
    MyAutoPtr<intin tp3(new int(20));

    //cout<<"ptr1= "<<*intp;
    cout<<"\n\t aap: ptr2= "<<*intp2;
    cout<<"\n\t aap: ptr3= "<<*intp3;

    intp3 = intp2; //
    =============== =============== 1

    cout<<"\n\t aap: ptr3= "<<*intp3;

    cout<<"\n\t aap: exiting app";
    }



    It seems, on debugging, that class's custom operator= is somehow not
    been called at 1 and hence a problem while destructing. (since delete
    is being called twice on the same pointer)
    ---------------------------------------------------------------------------------------------------------

    Q1. Any problems with the above code ?
    Q2. What is causing operator= not to be called and how to fix it ?
    Q3. Following statements (in the class interface) cause compiler
    errors, if not commented out

    private:
    T* pointee;
    //template <class U>
    //friend class MyAutoPtr<U>;

    MSDN defines this error as:-

    Compiler Error C3772
    Error Message
    "name" : invalid friend template declaration

    It is invalid to declare a friend of a class template specialization.
    You cannot declare an explicit or partial specialization of a class
    template and in the same statement declare a friend of that
    specialization. The name placeholder identifies the invalid
    declaration.
    To correct this error
    -Do not declare a friend of a class template specialization.
    -If appropriate for your application, declare a friend of the class
    template, or declare a friend of a particular partial or explicit
    specialization.

    Why such error, if this is not a specialization? or is it a
    specialization somehow?
    ---------------------------------------------------------------------------------------------------------

    Any help will be highly appreciated!

    Thanks!
  • Yakov Gerlovin

    #2
    Re: A Sample auto_ptr implementation

    Try to define assignment operator without template U parameter:

    //assignment operator
    MyAutoPtr<T>& operator=(MyAut oPtr<T>& rhs);

    Why do you need that 'U' anyway, release should return the pointer to
    be passed to reset, so T and U should be equal.

    Comment

    • Kai-Uwe Bux

      #3
      Re: A Sample auto_ptr implementation

      Ankur Arora wrote:
      Hi All,
      >
      I'm building a sample application that uses a custom auto_ptr
      implementation.
      The program crashes with the following output:-
      >
      Output (Debug Assertion failed)
      ----------
      >
      >
      release called
      copy constructor
      aap: ptr2= 10
      aap: ptr3= 20
      aap: ptr3= 10
      aap: exiting app
      Deleting pointee...10
      Deleting pointee...-572662307 (...problem ?)
      >
      Code
      --------
      Just a data point: your code works for me with output

      release called
      copy constructor
      aap: ptr2= 10
      aap: ptr3= 20
      Inside operator=
      Inside operator=, calling reset
      release called
      reset called
      aap: ptr3= 10
      aap: exiting app
      Deleting pointee...10

      So I just have nits:

      #include<iostre am>
      >
      using namespace std;
      It's a bad idea to use using namespace std in a header.



      [snip]
      template <class T>
      inline MyAutoPtr<T>::~ MyAutoPtr()
      {
      if(pointee)
      {
      cout<<"\n\t Deleting pointee..."<<*p ointee;
      delete pointee;
      }
      }
      delete will perform its own check for 0. It is required to be a null-op in
      that case.


      [snip]
      template<class T>
      template<class U>
      MyAutoPtr<T>& MyAutoPtr<T>::o perator=(MyAuto Ptr<U>& rhs)
      {
      cout<<"\n\t Inside operator=";
      if(this!=&rhs)
      This if-clause will not compile when T and U are different.

      You could use

      if ( this->pointee == rhs.pointee )

      instead (I think).
      {
      cout<<"\n\t Inside operator=, calling reset";
      reset(rhs.relea se());
      }
      return *this;
      }
      [snip]
      void main()
      [snip]

      Main returns int. I get an error with g++ at this point.

      It seems, on debugging, that class's custom operator= is somehow not
      been called at 1 and hence a problem while destructing. (since delete
      is being called twice on the same pointer)
      ---------------------------------------------------------------------------------------------------------
      >
      Q1. Any problems with the above code ?
      It works with g++.
      Q2. What is causing operator= not to be called and how to fix it ?
      A bug in your compiler?


      [snip]


      Best

      Kai-Uwe Bux

      Comment

      • Kai-Uwe Bux

        #4
        Re: A Sample auto_ptr implementation

        Yakov Gerlovin wrote:
        Try to define assignment operator without template U parameter:
        >
        //assignment operator
        MyAutoPtr<T>& operator=(MyAut oPtr<T>& rhs);
        >
        Why do you need that 'U' anyway, release should return the pointer to
        be passed to reset, so T and U should be equal.
        He needs it to support polymorphism. When D is derived from B, MyAutoPtr<B>
        should be constructible and assignable from MyAutoPtr<D>.

        But the OP could define copy-constructor and assignment operator from T
        separately. For the copy-constructor, I recall that this is needed. I am
        not sure if it is needed for the assignment operator.


        Best

        Kai-Uwe Bux

        Comment

        • anon

          #5
          Re: A Sample auto_ptr implementation

          [snip]
          >template <class T>
          >inline MyAutoPtr<T>::~ MyAutoPtr()
          >{
          > if(pointee)
          > {
          > cout<<"\n\t Deleting pointee..."<<*p ointee;
          > delete pointee;
          > }
          >}
          >
          delete will perform its own check for 0. It is required to be a null-op in
          that case.
          >
          Check for 0 is required for printing the debug message. Other then that,
          the check should be removed

          Comment

          • Ankur Arora

            #6
            Re: A Sample auto_ptr implementation

            On Oct 13, 2:36 pm, Yakov Gerlovin <yakov.gerlo... @gmail.comwrote :
            Try to define assignment operator without template U parameter:
            >
            //assignment operator
            MyAutoPtr<T>& operator=(MyAut oPtr<T>& rhs);
            >
            Why do you need that 'U' anyway, release should return the pointer to
            be passed to reset, so T and U should be equal.
            Hi Yakov,

            Thanks for the reply!

            Yes indeed when I remove the member template function i.e. change the
            function as you suggested, it works.
            But I don't know whats the problem with the first version.

            I should also mention that I'm using visual studio 2008 express
            edition.
            This be a compiler issue, u reckon?

            Thanks!

            Comment

            • Ankur Arora

              #7
              Re: A Sample auto_ptr implementation

              Thanks for the reply Kai!
              Please see the comments below.

              On Oct 13, 2:53 pm, Kai-Uwe Bux <jkherci...@gmx .netwrote:
              Ankur Arora wrote:
              Hi All,
              >
              I'm building a sample application that uses a custom auto_ptr
              implementation.
              The program crashes with the following output:-
              >
              Output               (Debug Assertion failed)
              ----------
              >
                       release called
                       copy constructor
                       aap: ptr2= 10
                       aap: ptr3= 20
                       aap: ptr3= 10
                       aap: exiting app
                       Deleting pointee...10
                       Deleting pointee...-572662307         (...problem ?)
              >
              Code
              --------
              >
              Just a data point: your code works for me with output
              >
                       release called
                       copy constructor
                       aap: ptr2= 10
                       aap: ptr3= 20
                       Inside operator=
                       Inside operator=, calling reset
                       release called
                       reset called
                       aap: ptr3= 10
                       aap: exiting app
                       Deleting pointee...10
              >
              So I just have nits:
              >
              #include<iostre am>
              >
              using namespace std;
              >
              It's a bad idea to use using namespace std in a header.
              >
              Agreed!
              [snip]
              >
              template <class T>
              inline MyAutoPtr<T>::~ MyAutoPtr()
              {
                if(pointee)
                {
                  cout<<"\n\t Deleting pointee..."<<*p ointee;
                  delete pointee;
                 }
              }
              >
              delete will perform its own check for 0. It is required to be a null-op in
              that case.
              I did this since removing this check caused the program to crash, even
              though I had made pointee equals to 0 in release(), which was used in
              the copy constructor.
              I'm using visual studio 2008 express edition. You reckon this is a
              complier issue?
              >
              [snip]
              >
              template<class T>
              template<class U>
              MyAutoPtr<T>& MyAutoPtr<T>::o perator=(MyAuto Ptr<U>& rhs)
              {
                cout<<"\n\t Inside operator=";
                if(this!=&rhs)
              >
              This if-clause will not compile when T and U are different.
              >
              You could use
              >
                if ( this->pointee == rhs.pointee )
              >
              instead (I think).
              >
              I saw this example in "More Effective C++" by scott meyers. This was
              how its used in that book. Here is a code.

              //Interface
              template<class T>
              class auto_ptr {
              public:
              explicit auto_ptr(T *p = 0); // see Item 5 for a
              // description of
              "explicit"
              template<class U // copy constructor member
              auto_ptr(auto_p tr<U>& rhs); // template (see Item 28):
              // initialize a new
              auto_ptr
              // with any compatible
              // auto_ptr
              ~auto_ptr();
              template<class U // assignment operator
              auto_ptr<T>& // member template (see
              operator=(auto_ ptr<U>& rhs); // Item 28): assign from
              any
              // compatible auto_ptr
              T& operator*() const; // see Item 28
              T* operator->() const; // see Item 28
              T* get() const; // return value of current
              // dumb pointer
              T* release(); // relinquish ownership of
              // current dumb pointer
              and
              // return its value
              void reset(T *p = 0); // delete owned pointer;
              // assume ownership of p
              private:
              T *pointee;
              template<class U // make all auto_ptr
              classes
              friend class auto_ptr<U>; // friends of one another
              };

              //Implementation
              template<class T>
              inline auto_ptr<T>::au to_ptr(T *p)
              : pointee(p)
              {}
              template<class T>
              inline auto_ptr<T>::au to_ptr(auto_ptr <U>& rhs)
              : pointee(rhs.rel ease())
              {}
              template<class T>
              inline auto_ptr<T>::~a uto_ptr()
              { delete pointee; }
              template<class T>
              template<class U>
              inline auto_ptr<T>& auto_ptr<T>::op erator=(auto_pt r<U>& rhs)
              {
              if (this != &rhs) reset(rhs.relea se());
              return *this;
              }
              template<class T>
              inline T& auto_ptr<T>::op erator*() const
              { return *pointee; }
              template<class T>
              inline T* auto_ptr<T>::op erator->() const
              { return pointee; }
              template<class T>
              inline T* auto_ptr<T>::ge t() const
              { return pointee; }
              template<class T>
              inline T* auto_ptr<T>::re lease()
              {
              T *oldPointee = pointee;
              pointee = 0;
              return oldPointee;
              }
              template<class T>
              inline void auto_ptr<T>::re set(T *p)
              {
              if (pointee != p) {
              delete pointee;
              pointee = p;
              }
              }



              Anything wrong with the above ? (would be surprised if there is, as it
              came from scott meyers)


              Q1. Any problems with the above code ?
              >
              It works with g++.
              >
              Again, looks like an issue with visual studio 2008 express.
              Q2. What is causing operator= not to be called and how to fix it ?
              >
              A bug in your compiler?
              >
              [snip]
              >
              Best
              >
              Kai-Uwe Bux

              Comment

              • Barry

                #8
                Re: A Sample auto_ptr implementation

                On Oct 13, 10:10 pm, Ankur Arora <ankuraror...@g mail.comwrote:
                Thanks for the reply Kai!
                Please see the comments below.
                >
                On Oct 13, 2:53 pm, Kai-Uwe Bux <jkherci...@gmx .netwrote:
                >
                Ankur Arora wrote:
                Hi All,
                >
                I'm building a sample application that uses a custom auto_ptr
                implementation.
                The program crashes with the following output:-
                >
                Output               (Debug Assertion failed)
                ----------
                >
                         release called
                         copy constructor
                         aap: ptr2= 10
                         aap: ptr3= 20
                         aap: ptr3= 10
                         aap: exiting app
                         Deleting pointee...10
                         Deleting pointee...-572662307         (...problem ?)
                >
                Code
                --------
                >
                Just a data point: your code works for me with output
                >
                         release called
                         copy constructor
                         aap: ptr2= 10
                         aap: ptr3= 20
                         Inside operator=
                         Inside operator=, calling reset
                         release called
                         reset called
                         aap: ptr3= 10
                         aap: exiting app
                         Deleting pointee...10
                >
                So I just have nits:
                >
                #include<iostre am>
                >
                using namespace std;
                >
                It's a bad idea to use using namespace std in a header.
                >
                Agreed!
                >
                [snip]
                >
                template <class T>
                inline MyAutoPtr<T>::~ MyAutoPtr()
                {
                  if(pointee)
                  {
                    cout<<"\n\t Deleting pointee..."<<*p ointee;
                    delete pointee;
                   }
                }
                >
                delete will perform its own check for 0. It is required to be a null-opin
                that case.
                >
                I did this since removing this check caused the program to crash, even
                though I had made pointee equals to 0 in release(), which was used in
                the copy constructor.
                I'm using visual studio 2008 express edition. You reckon this is a
                complier issue?
                >
                >
                >
                >
                >
                [snip]
                >
                template<class T>
                template<class U>
                MyAutoPtr<T>& MyAutoPtr<T>::o perator=(MyAuto Ptr<U>& rhs)
                {
                  cout<<"\n\t Inside operator=";
                  if(this!=&rhs)
                >
                This if-clause will not compile when T and U are different.
                >
                You could use
                >
                  if ( this->pointee == rhs.pointee )
                >
                instead (I think).
                >
                I saw this example in "More Effective C++" by scott meyers. This was
                how its used in that book. Here is a code.
                >
                //Interface
                template<class T>
                class auto_ptr {
                public:
                  explicit auto_ptr(T *p = 0);              // see Item5 for a
                                                            // description of
                "explicit"
                  template<class U                        // copy constructor member
                  auto_ptr(auto_p tr<U>& rhs);               // template (see Item 28):
                                                            // initialize a new
                auto_ptr
                                                            // with any compatible
                                                            // auto_ptr
                  ~auto_ptr();
                  template<class U                        // assignment operator
                  auto_ptr<T>&                              // member template (see
                  operator=(auto_ ptr<U>& rhs);              // Item 28): assign from
                any
                                                            // compatible auto_ptr
                  T& operator*() const;                     // see Item 28
                  T* operator->() const;                    // see Item 28
                  T* get() const;                           // return value of current
                                                            // dumb pointer
                  T* release();                            // relinquish ownership of
                                                            // current dumb pointer
                and
                                                            // return its value
                  void reset(T *p = 0);                     // delete owned pointer;
                                                            // assume ownership of p
                private:
                  T *pointee;
                template<class U                          // make all auto_ptr
                classes
                friend class auto_ptr<U>;                   // friends of one another
                >
                };
                >
                //Implementation
                template<class T>
                inline auto_ptr<T>::au to_ptr(T *p)
                : pointee(p)
                {}
                template<class T>
                  inline auto_ptr<T>::au to_ptr(auto_ptr <U>& rhs)
                  : pointee(rhs.rel ease())
                  {}
                template<class T>
                inline auto_ptr<T>::~a uto_ptr()
                { delete pointee; }
                template<class T>
                  template<class U>
                  inline auto_ptr<T>& auto_ptr<T>::op erator=(auto_pt r<U>& rhs)
                  {
                    if (this != &rhs) reset(rhs.relea se());
                    return *this;
                  }
                template<class T>
                inline T& auto_ptr<T>::op erator*() const
                { return *pointee; }
                template<class T>
                inline T* auto_ptr<T>::op erator->() const
                { return pointee; }
                template<class T>
                inline T* auto_ptr<T>::ge t() const
                { return pointee; }
                template<class T>
                inline T* auto_ptr<T>::re lease()
                {
                  T *oldPointee = pointee;
                  pointee = 0;
                  return oldPointee;}
                >
                template<class T>
                inline void auto_ptr<T>::re set(T *p)
                {
                  if (pointee != p) {
                    delete pointee;
                    pointee = p;
                  }
                >
                }
                >
                Anything wrong with the above ? (would be surprised if there is, as it
                came from scott meyers)
                >
                Q1. Any problems with the above code ?
                There's a reversion for auto_ptr (IIRC, a article is proviede by Mayer
                on
                this), adding auto_ptr_ref for conversion, which supports rvalue
                initialization for auto_ptr. which is done transparently.

                void fun(auto_ptr<Tp tr);
                fun(auto_ptr(ne w T)); // rvalue -auto_ptr_ref -auto_ptr
                >
                It works with g++.
                >
                Again, looks like an issue with visual studio 2008 express.
                there are two problem with visual C++ 2005 in this issue:
                1. as extension, "explicit" does NOT work as standard says.
                needs /Za switch to turn it off.

                2. auto_ptr_ref use void* rather T*

                point 2 is fixed by VS 2008(none expression version,
                but I expression version should ship the same lib)
                >
                Q2. What is causing operator= not to be called and how to fix it ?
                >
                A bug in your compiler?
                >
                [snip]
                --
                Best Regards
                Barry

                Comment

                • Ankur Arora

                  #9
                  Re: A Sample auto_ptr implementation

                  On Oct 13, 5:06 pm, Barry <dhb2...@gmail. comwrote:
                  On Oct 13, 10:10 pm, Ankur Arora <ankuraror...@g mail.comwrote:
                  >
                  >
                  >
                  Thanks for the reply Kai!
                  Please see the comments below.
                  >
                  On Oct 13, 2:53 pm, Kai-Uwe Bux <jkherci...@gmx .netwrote:
                  >
                  Ankur Arora wrote:
                  Hi All,
                  >
                  I'm building a sample application that uses a custom auto_ptr
                  implementation.
                  The program crashes with the following output:-
                  >
                  Output               (Debug Assertion failed)
                  ----------
                  >
                           release called
                           copy constructor
                           aap: ptr2= 10
                           aap: ptr3= 20
                           aap: ptr3= 10
                           aap: exiting app
                           Deleting pointee...10
                           Deleting pointee...-572662307         (....problem ?)
                  >
                  Code
                  --------
                  >
                  Just a data point: your code works for me with output
                  >
                           release called
                           copy constructor
                           aap: ptr2= 10
                           aap: ptr3= 20
                           Inside operator=
                           Inside operator=, calling reset
                           release called
                           reset called
                           aap: ptr3= 10
                           aap: exiting app
                           Deleting pointee...10
                  >
                  So I just have nits:
                  >
                  #include<iostre am>
                  >
                  using namespace std;
                  >
                  It's a bad idea to use using namespace std in a header.
                  >
                  Agreed!
                  >
                  [snip]
                  >
                  template <class T>
                  inline MyAutoPtr<T>::~ MyAutoPtr()
                  {
                    if(pointee)
                    {
                      cout<<"\n\t Deleting pointee..."<<*p ointee;
                      delete pointee;
                     }
                  }
                  >
                  delete will perform its own check for 0. It is required to be a null-op in
                  that case.
                  >
                  I did this since removing this check caused the program to crash, even
                  though I had made pointee equals to 0 in release(), which was used in
                  the copy constructor.
                  I'm using visual studio 2008 express edition. You reckon this is a
                  complier issue?
                  >
                  [snip]
                  >
                  template<class T>
                  template<class U>
                  MyAutoPtr<T>& MyAutoPtr<T>::o perator=(MyAuto Ptr<U>& rhs)
                  {
                    cout<<"\n\t Inside operator=";
                    if(this!=&rhs)
                  >
                  This if-clause will not compile when T and U are different.
                  >
                  You could use
                  >
                    if ( this->pointee == rhs.pointee )
                  >
                  instead (I think).
                  >
                  I saw this example in "More Effective C++" by scott meyers. This was
                  how its used in that book. Here is a code.
                  >
                  //Interface
                  template<class T>
                  class auto_ptr {
                  public:
                    explicit auto_ptr(T *p = 0);              // see Item 5 for a
                                                             // description of
                  "explicit"
                    template<class U                        // copy constructor member
                    auto_ptr(auto_p tr<U>& rhs);               // template(see Item 28):
                                                             // initialize a new
                  auto_ptr
                                                             // with any compatible
                                                             // auto_ptr
                    ~auto_ptr();
                    template<class U                        // assignment operator
                    auto_ptr<T>&                              // member template (see
                    operator=(auto_ ptr<U>& rhs);              // Item 28): assign from
                  any
                                                             // compatible auto_ptr
                    T& operator*() const;                     // see Item 28
                    T* operator->() const;                    // see Item 28
                    T* get() const;                          // return value of current
                                                             // dumb pointer
                    T* release();                             // relinquish ownership of
                                                             // current dumb pointer
                  and
                                                             // return its value
                    void reset(T *p = 0);                     // delete owned pointer;
                                                             // assume ownership of p
                  private:
                    T *pointee;
                  template<class U                          // make all auto_ptr
                  classes
                  friend class auto_ptr<U>;                   // friends of one another
                  >
                  };
                  >
                  //Implementation
                  template<class T>
                  inline auto_ptr<T>::au to_ptr(T *p)
                  : pointee(p)
                  {}
                  template<class T>
                    inline auto_ptr<T>::au to_ptr(auto_ptr <U>& rhs)
                    : pointee(rhs.rel ease())
                    {}
                  template<class T>
                  inline auto_ptr<T>::~a uto_ptr()
                  { delete pointee; }
                  template<class T>
                    template<class U>
                    inline auto_ptr<T>& auto_ptr<T>::op erator=(auto_pt r<U>& rhs)
                    {
                      if (this != &rhs) reset(rhs.relea se());
                      return *this;
                    }
                  template<class T>
                  inline T& auto_ptr<T>::op erator*() const
                  { return *pointee; }
                  template<class T>
                  inline T* auto_ptr<T>::op erator->() const
                  { return pointee; }
                  template<class T>
                  inline T* auto_ptr<T>::ge t() const
                  { return pointee; }
                  template<class T>
                  inline T* auto_ptr<T>::re lease()
                  {
                    T *oldPointee = pointee;
                    pointee = 0;
                    return oldPointee;}
                  >
                  template<class T>
                  inline void auto_ptr<T>::re set(T *p)
                  {
                    if (pointee != p) {
                      delete pointee;
                      pointee = p;
                    }
                  >
                  }
                  >
                  Anything wrong with the above ? (would be surprised if there is, as it
                  came from scott meyers)
                  >
                  Q1. Any problems with the above code ?
                  >
                  There's a reversion for auto_ptr (IIRC, a article is proviede by Mayer
                  on
                  this), adding auto_ptr_ref for conversion, which supports rvalue
                  initialization for auto_ptr. which is done transparently.
                  >
                  void fun(auto_ptr<Tp tr);
                  fun(auto_ptr(ne w T)); // rvalue -auto_ptr_ref -auto_ptr
                  >
                  >
                  >
                  It works with g++.
                  >
                  Again, looks like an issue with visual studio 2008 express.
                  >
                  there are two problem with visual C++ 2005 in this issue:
                  1. as extension, "explicit" does NOT work as standard says.
                     needs /Za switch to turn it off.
                  >
                  2. auto_ptr_ref use void* rather T*
                  >
                  point 2 is fixed by VS 2008(none expression version,
                  but I expression version should ship the same lib)
                  >
                  >
                  >
                  Q2. What is causing operator= not to be called and how to fix it ?
                  >
                  A bug in your compiler?
                  >
                  [snip]
                  >
                  --
                  Best Regards
                  Barry
                  Thanks Barry.

                  Comment

                  • Hendrik Schober

                    #10
                    Re: A Sample auto_ptr implementation

                    Barry wrote:
                    [...]
                    There's a reversion for auto_ptr (IIRC, a article is proviede by Mayer
                    on
                    this), adding auto_ptr_ref for conversion, which supports rvalue
                    initialization for auto_ptr. which is done transparently.
                    The guy's name is Scott Meyers and the article is here:

                    [...]
                    there are two problem with visual C++ 2005 in this issue:
                    1. as extension, "explicit" does NOT work as standard says.
                    needs /Za switch to turn it off.
                    Do you have a repro for this? I'd be very interested.
                    [...]
                    Barry
                    Schobi

                    Comment

                    • Barry

                      #11
                      Re: A Sample auto_ptr implementation

                      On Oct 15, 11:22 pm, Hendrik Schober <spamt...@gmx.d ewrote:
                      Barry wrote:
                      [...]
                      There's a reversion for auto_ptr (IIRC, a article is proviede by Mayer
                      on
                      this), adding auto_ptr_ref for conversion, which supports rvalue
                      initialization for auto_ptr. which is done transparently.
                      >
                        The guy's name is Scott Meyers and the article is here:
                         http://www.aristeia.com/BookErrata/auto_ptr-update.html
                      >
                      [...]
                      there are two problem with visual C++ 2005 in this issue:
                      1. as extension, "explicit" does NOT work as standard says.
                         needs /Za switch to turn it off.
                      >
                        Do you have a repro for this? I'd be very interested.
                      >
                      #include <memory>

                      int main()
                      {
                      std::auto_ptr<i ntp1 = new int(10); // this shouldn't work
                      std::auto_ptr<i ntp2(new int(10)); // should be like this!
                      }

                      =============== ==
                      d:\>cl /EHsc test.cpp

                      Compile successfully!
                      =============== ==

                      d:\>cl /EHsc /Za test.cpp
                      cl /EHsc /Za test.cpp
                      Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42
                      for 80x86
                      Copyright (C) Microsoft Corporation. All rights reserved.

                      test.cpp
                      test.cpp(5) : error C2440: 'initializing' : cannot convert from 'int
                      *' to 'std::auto_ptr< _Ty>'
                      with
                      [
                      _Ty=int
                      ]
                      Constructor for class 'std::auto_ptr< _Ty>' is declared
                      'explicit'
                      with
                      [
                      _Ty=int
                      ]

                      =============== ============

                      --
                      Best Regards
                      Barry

                      Comment

                      • Hendrik Schober

                        #12
                        Re: A Sample auto_ptr implementation

                        Barry wrote:
                        On Oct 15, 11:22 pm, Hendrik Schober <spamt...@gmx.d ewrote:
                        >Barry wrote:
                        >>[...]
                        >>There's a reversion for auto_ptr (IIRC, a article is proviede by Mayer
                        >>on
                        >>this), adding auto_ptr_ref for conversion, which supports rvalue
                        >>initializatio n for auto_ptr. which is done transparently.
                        > The guy's name is Scott Meyers and the article is here:
                        > http://www.aristeia.com/BookErrata/auto_ptr-update.html
                        >>
                        >>[...]
                        >>there are two problem with visual C++ 2005 in this issue:
                        >>1. as extension, "explicit" does NOT work as standard says.
                        >> needs /Za switch to turn it off.
                        > Do you have a repro for this? I'd be very interested.
                        >>
                        >
                        #include <memory>
                        >
                        int main()
                        {
                        std::auto_ptr<i ntp1 = new int(10); // this shouldn't work
                        std::auto_ptr<i ntp2(new int(10)); // should be like this!
                        }
                        [...]
                        Thanks.
                        It doesn't seem to be a compielr bug, though, as a simple
                        test with my own class makes the first line fail.

                        Schobi

                        Comment

                        • Barry

                          #13
                          Re: A Sample auto_ptr implementation

                          On Oct 17, 6:16 pm, Hendrik Schober <spamt...@gmx.d ewrote:
                          Barry wrote:
                          On Oct 15, 11:22 pm, Hendrik Schober <spamt...@gmx.d ewrote:
                          Barry wrote:
                          >[...]
                          >There's a reversion for auto_ptr (IIRC, a article is proviede by Mayer
                          >on
                          >this), adding auto_ptr_ref for conversion, which supports rvalue
                          >initializati on for auto_ptr. which is done transparently.
                            The guy's name is Scott Meyers and the article is here:
                             http://www.aristeia.com/BookErrata/auto_ptr-update.html
                          >
                          >[...]
                          >there are two problem with visual C++ 2005 in this issue:
                          >1. as extension, "explicit" does NOT work as standard says.
                          >   needs /Za switch to turn it off.
                            Do you have a repro for this? I'd be very interested.
                          >
                          #include <memory>
                          >
                          int main()
                          {
                              std::auto_ptr<i ntp1 = new int(10); // this shouldn't work
                              std::auto_ptr<i ntp2(new int(10));  // should be like this!
                          }
                          [...]
                          >
                            Thanks.
                            It doesn't seem to be a compielr bug, though, as a simple
                            test with my own class makes the first line fail.
                          >
                          Maybe some Serive Package fix this.
                          I tried the code on Dinkumware

                          it fails too.

                          --
                          Best Regards
                          Barry


                          Comment

                          • James Kanze

                            #14
                            Re: A Sample auto_ptr implementation

                            On Oct 13, 2:58 pm, Kai-Uwe Bux <jkherci...@gmx .netwrote:
                            Yakov Gerlovin wrote:
                            Try to define assignment operator without template U
                            parameter:
                            //assignment operator
                            MyAutoPtr<T>& operator=(MyAut oPtr<T>& rhs);
                            Why do you need that 'U' anyway, release should return the
                            pointer to be passed to reset, so T and U should be equal.
                            He needs it to support polymorphism. When D is derived from B,
                            MyAutoPtr<Bshou ld be constructible and assignable from
                            MyAutoPtr<D>.
                            But the OP could define copy-constructor and assignment
                            operator from T separately. For the copy-constructor, I recall
                            that this is needed. I am not sure if it is needed for the
                            assignment operator.
                            If I understand the context correctly, it is. A template
                            operator= will never stop the compiler from generating its
                            default copy operator=.

                            --
                            James Kanze (GABI Software) email:james.kan ze@gmail.com
                            Conseils en informatique orientée objet/
                            Beratung in objektorientier ter Datenverarbeitu ng
                            9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

                            Comment

                            • James Kanze

                              #15
                              Re: A Sample auto_ptr implementation

                              On Oct 13, 1:58 pm, Ankur Arora <ankuraror...@g mail.comwrote:
                              I'm building a sample application that uses a custom auto_ptr
                              implementation. The program crashes with the following
                              output:-
                              Output               (Debug Assertion failed)
                              ----------
                                       release called
                                       copy constructor
                                       aap: ptr2= 10
                                       aap: ptr3= 20
                                       aap: ptr3= 10
                                       aap: exiting app
                                       Deleting pointee...10
                                       Deleting pointee...-572662307         (...problem ?)
                              Code
                              --------
                              #include<iostre am>
                              using namespace std;
                              // MyAutoPtr Interface
                              template <class T>
                              class MyAutoPtr
                              {
                                      public:
                                              explicit MyAutoPtr(T* ptr=0);
                                              ~MyAutoPtr();
                                              template <class U>
                                              MyAutoPtr(MyAut oPtr<U*rhs);
                                              //copy constructor member template, initialize
                              //this member pointer
                              //with any other compatible auto_ptr
                                              template <class U>
                                              MyAutoPtr(MyAut oPtr<U>& rhs);
                              This is NOT a copy constructor, according to the standard, and
                              it will not prevent the compiler from generating its default
                              copy constructor.
                                              //assignment operator
                                              template <class U>
                                              MyAutoPtr<T>& operator=(MyAut oPtr<U>& rhs);
                              And this is NOT a copy assignment operator, and will not prevent
                              the compiler from generating its own.

                              Note that in the two cases above, the compiler will generate its
                              own versions of the functions, but they will have an argument
                              type MyAutoPtr<Tcons t&; not non-const. Which means that in
                              some cases, when copying, the template version you provide will
                              be called, rather than the official copy constructor or copy
                              assignment operator. (I know it sounds wierd, but it's really
                              rather logical: overload resolution is applied, regardless of
                              whether the context involves "copying" or not. Template
                              functions are never considered "copy" operators, but if overload
                              resolution chooses one, that's what gets called.)
                                              //relinquish ownership
                                              T* release();
                                              T* get() const;
                                              //reset the auto_ptr, delete pointee, assume ownership of p
                                              void reset(T* ptr=0);
                                              T& operator*() const;
                                              T* operator->() const;
                                      private:
                                              T* pointee;
                                              //template <class U>
                                              //friend class MyAutoPtr<U>;
                              };
                              //Implementation
                              [... just does the obvious things]
                              void main()
                              Shouldn't compile:-).
                              {
                                      MyAutoPtr<intin tp(new int(10));
                                      MyAutoPtr<intin tp2(intp);
                                      MyAutoPtr<intin tp3(new int(20));
                              Now comes the fun part. Note that all of your instances are for
                              the same type. So the compiler generated functions will come
                              into consideration.

                              Note too that when intp and intp3 go out of scope, they're going
                              to use a non-array delete on memory that was allocated with an
                              array new. Undefined behavior.
                                      //cout<<"ptr1= "<<*intp;
                                      cout<<"\n\t aap: ptr2= "<<*intp2;
                                      cout<<"\n\t aap: ptr3= "<<*intp3;
                                      intp3 = intp2;      // =============== =============== 1
                              >
                                      cout<<"\n\t aap: ptr3= "<<*intp3;
                                      cout<<"\n\t aap: exiting app";
                              }
                              It seems, on debugging, that class's custom operator= is
                              somehow not been called at 1 and hence a problem while
                              destructing.
                              This would be a compiler error, but a subtle one. Since intp2
                              is a non-const lvalue, overload resolution should choose your
                              template'd operator= over the compiler generated one (which is
                              none the less present). Given that the context is copy, it
                              looks like the compiler is using copy assignment operator,
                              without doing full overload resolution.
                              (since delete
                              is being called twice on the same pointer)
                              --------------------------------------------
                              Q1. Any problems with the above code ?
                              IMHO, yes. The fact that you've let the compiler generate its
                              default versions will lead to runtime errors which may be
                              difficult to check. (Basically, you can assign a const or a
                              temporary MyAutoPtr, with the wrong semantics.) At the very
                              least, you should declare and define the copy constructor and
                              the assignment operator you want: non-template functions taking
                              a MyAutoPtr<T>& (and not the MyAutoPtr<Tcons t& that the
                              compiler will generate here).
                              Q2. What is causing operator= not to be called and how to fix
                              it ?
                              It looks like a compiler error, but I suspect that my
                              recommendations concerning Q1 will also fix it.

                              --
                              James Kanze (GABI Software) email:james.kan ze@gmail.com
                              Conseils en informatique orientée objet/
                              Beratung in objektorientier ter Datenverarbeitu ng
                              9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

                              Comment

                              Working...