Topic: Extending auto_ptr


Author: gregor@netcom.com (Greg Colvin)
Date: 1996/05/21
Raw View
In article <xso4tpet31m.fsf@avs.cs.rpi.edu> vandevod@cs.rpi.edu (David Vandevoorde) writes:
...
>In fact, I find `get()' redundant. Why not use:
>
> int* p = ai.operator->(); // ;-) ?
>
Actually, I prefer
   int* p = &*ai;

In general, auto_ptr generates far more controversy than it warrants, perhaps
because it is small enough to specify and implement in one page, and because
almost any advanced C++ programmer has needed and implemented something like
it, so we all have our opinions about how to do it best.  My attitude is this:
use the standard auto_ptr in specifying interfaces, so as to make your intent
clear to the rest of us, but go ahead and write your own templates that add
to auto_ptr whatever other functionality you want in your implementations of
those interfaces.
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Nathan Myers <ncm@cantrip.org>
Date: 1996/05/21
Raw View
Paul J. Lucas wrote:
> In <319A5B70.6A82948C@cantrip.org> Nathan Myers <ncm@cantrip.org> writes:
> >Paul J. Lucas wrote:
> >>         ...  why doesn't
> >>         auto_ptr ... contain: [snip]
> >>            Doesn't this eliminate a temporary by allowing an ordinary
> >>            pointer to be assigned to an auto_ptr directly?
>
> >auto_ptr<> is implemented inline, so temporaries don't matter -- they
> >can be optimized away.
>
>         Why rely on compiler vendors to do the right thing?

Compiler vendors have tremendous latitude.  Tightening the auto_ptr<>
spec will have little impact on performance. Though auto_ptr<> benefits
from optimizations of other performance-critical code, performance of
code that uses auto_ptr<> tends to be dominated by the time spent in
new() and delete(), just because typical libraries implement those
functions so abysmally.

> >Also, this hides the conversion, a bad thing when the two types are not
> >actually interchangeable.
>
>         Could you please exaborate on what you mean by "this hides the
>         conversion."  Hides _what_ conversion?  Obviously, it's being
>         converted from a built-in pointer to an anto_ptr, so what
>         conversion are you talking about?

If you look at the code using the assignment, all you
see is an assignment, but that's not all that is happening;
a pointer is being adopted into an auto_ptr<>; ownership
is being transferred.  This should be visible.

> >>         2.
> >>                 operator T*() const { return get(); }
> >>
> >>                 This makes the following code legal:
> >>
> >>                         auto_ptr<int> ai;
> >>                         int *p = ai;            // illegal otherwise
>
> >Automatic conversions are generally a nightmare.  This conversion
> >would allow ordinary pointers to leak out invisibly.
>
>         No, they allow ordinary pointers to receive the value of an
>         auto_ptr.  There is no "leak" here: "leak" usually means that an
>         object is allocated, but never deallocated.  Assignment to a
>         built-in pointer does not cause a memory leak.

"Leak" means fluid escaping a conduit.  We talk about leaks in software
systems by analogy.  My analogy involves pointer ownership.  It's not
hard, with lots of invisible conversions, to construct plausible examples
in which two auto_ptr<> objects both "own" the same pointer value.

> Given that the above _specific_ conversion does
>         no harm as far as I can see, ignoring the fact that (you think)
>         automatic conversions are generally a nightmare, I see no
>         reason to make code syntactically ugly:
>
>                 int *p = ai.get();              // why??

You can ignore anything you like; the committee hasn't that liberty.
Personally, I expressed a preference for naming that member "leak()".

> >>         3.
> >>                 typedef T value_type;
> >>
> >>            This allows you to get at the type so you can write totally
> >>            paramaterized functions because you can declare an instance
> >>            of the type to which an auto_ptr points.
>
> >This has been added (though it's called "element_type").
>
>         Then, IMHO, it's not consistent with "value_type" being used
>         all over the place in STL containers.  Was this a _conscious_
>         decision to make it (annoyingly) different?

You are invited to join the committee and put in volunteer time
working on the Draft along with the rest of us.  I should warn you
that it can be a great deal of (apparently thankless) work.

> >>         4. For my set of pointer classes, there was a base pointer
> >>            class: [comp_ptr]
>
> >Sorry, I don't see what good it does to derive from comp_ptr.
>
>         OK, but you never commented on the utility of comp_ptr unto
>         itself.

I prefer to stay on-topic.  (comp.lang.c++.moderated is a good place
to discuss the merits (or lack thereof) of design ideas.)
In any case, it has been well-answered by a previous poster.

> >If we (always) wanted these semantics we could put them in auto_ptr
> >directly, or (better, IMHO) use a comparison object passed to the
> >container.
>
>         Example, please.

Someone else posted a good example.

> >>         5. There can also be a clone_ptr class: [ snip ]
>
> >This could be useful.  The criterion for inclusion in the standard wasn't
> >whether something might be useful, but whether it was (somehow) necessary.
> >Many committee members believed auto_ptr was necessary and (just)
> >sufficient.
>
>         Why was it considered necessary?  Necessary for what?  Where
>         else in the standard library is auto_ptr used such that it is
>         necessary to have it?

It was considered necessary as an aid for users writing exception-safe
code.  Period.

> >If you start listing things that could be put in because they might
> >be useful, it is hard to know when (if ever) you will finish.
>
>         Is every container and every algorithm in STL *necessary*?  If
>         you want to be minimalistic about it, everything other than the
>         streams library and the RTTI stuff to support that feature of
>         C++ isn't *necessary* at all.

Necessity is (necessarily) as perceived by those who were interested enough
to attend the meetings and volunteer the time to work on the standard.  What
other criteria would you suggest?  The time for adding entirely new things
is well past, in the perception of the committee members and most of their
consituents.

>         Copying data structures containing heterogeneous objects is a
>         fairly common thing to do in OO programs.  A standard way of
>         doing it could be deemed necessary.

You can deem anything; so can I.  Convincing a human structure containing
heterogeneous persons is a different matter.  That takes hard work, a
flexible attitude, an adaptable sense of priorities, and a willingness
to listen carefully.  I don't mean to suggest anybody here lacks those
attributes, but this newsgroup doesn't really evoke them as well as
the face-to-face meetings (sometimes) do.

Nathan Myers
ncm@cantrip.org  http://www.cantrip.org/
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Rob Stewart <stew@datalytics.com>
Date: 1996/05/21
Raw View
Steve Willer wrote:
>
> pjl@ptolemy-ethernet.arc.nasa.gov (Paul J. Lucas) wrote:
>
> >>>         1.
> >>>                 auto_ptr<T>& operator=( T *p ) {
> >>>                         reset( p );
> >>>                         return *this;
> >>>                 }
> >>>[snip]
>
>   auto_ptr<int> a = new int(getavaluefora());
>   int *b = new int(getavalueforb());
>   a = b;          // oops! I meant "*a = *b"!
>   delete b;
>
> This code would generate a run-time error, which might not show up until
> it's at your customer's site. Without the constructor mentioned above,
> there would be no temporaries created, so there would therefore be no
> opportunity for a compiler to even warn you about this problem.
>
> My compiler warns me about the creation of temporaries (like if you give
> a "char*" to a function that expects a "const string&"), and I deeply
> appreciate this feature. It gives me the opportunity to find out errors
> like the one above. Your change to auto_ptr removes the opportunity to
> find these errors and gives a negligible gain.

Does every compiler do this, and should it?  What's good for the
goose isn't necessarily good for the gander.

> >>>         2.
> >>>                 operator T*() const { return get(); }
>
> >>Automatic conversions are generally a nightmare.  This conversion
> >>would allow ordinary pointers to leak out invisibly.
> >
> >       No, they allow ordinary pointers to receive the value of an
> >       auto_ptr.  There is no "leak" here: "leak" usually means that an
> >       object is allocated, but never deallocated.  Assignment to a
> >       built-in pointer does not cause a memory leak.
>
> User-defined conversion operators are pretty universally accepted as
> something to be avoided if at all possible. That's why string

But you don't omit them because they are "something to be
avoided."  You weigh the consequences and decide whether to use
them.  So, do you have a specific reason for excluding his
conversion operator?

[snip]
> >       Copying data structures containing heterogeneous objects is a
> >       fairly common thing to do in OO programs.  A standard way of
> >       doing it could be deemed necessary.
>
> Perhaps it would have been nice to have this ability, but it doesn't
> bother me overly. First of all, it is _not_ as important or necessary to
> the language as the auto_ptr. Second of all, it would take a very short
> time to make up a pointer that would work for heterogeneous objects in a
> container library such as the STL. Why not just spend the time and write
> your own?

So, the rules for determining what should and shouldn't be
included in the standard is what is important to you?  Don't you
see that you're both saying the same thing?  "I think its common
and important so it should have been in the standard."  "Well, I
don't use it much, so I think they were right to leave it out."

Those on the commitee have the unenviable job of trying to
determine what will have the most utility to the most people
without imposing undue restrictions on anyone.  They try to
include only those things that are necessary to stop the
proliferation of different implementations when those implements
are deterimental.

Consider bool as an example.  Most everyone uses boolean
variables.  Most everyone created their own type for it.  Some
made typedefs, others classes, others manifest constants and
ints.  It was clearly advantageous to all concerned to add a
bool type to the language.  It will allow everyone to converge
on a single type and behavior for the type.

auto_ptr is less obvious since there are so many ways to
implement it, and so many things it could do.  What works for
one won't necessarily work for another.  What is sufficient for
one isn't necessarily sufficient for another.  However, since
auto_ptr is a class, you can derive from it to add functionality
you see as necessary.  You can also choose to scrap auto_ptr and
implement your own.  Either way, the standard has provided
commonality and has allowed you to extend or replace its
behavior, as you see fit.

Besides, there is room left for companies like Rogue Wave or
developers like you to add value to the standard.

--
Robert Stewart  | My opinions are usually my own.
Datalytics, Inc. | stew@datalytics.com
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: willer@carolian.com (Steve Willer)
Date: 1996/05/21
Raw View
Rob Stewart <stew@datalytics.com> wrote:

>> My compiler warns me about the creation of temporaries (like if you give
>> a "char*" to a function that expects a "const string&"), and I deeply
>> appreciate this feature. It gives me the opportunity to find out errors
>> like the one above. Your change to auto_ptr removes the opportunity to
>> find these errors and gives a negligible gain.
>
>Does every compiler do this, and should it?  What's good for the
>goose isn't necessarily good for the gander.

I'm not sure why you're responding in this manner. Of course, any user
who doesn't like a particular warning can always turn them off.

The point I was trying to make is that it doesn't make much sense to
warn about implicit conversions that have been explicitly allowed by the
library designer, so there's no protection is there is an
auto_ptr<T>::operator T*().  But since creation of temporaries for
single-argument constructors may be a result of an oversight, it does
make sense for a compiler to warn about it, and I personally am quite
happy that my compiler does so. If someone else doesn't want it, that's
fine...they can turn the warning off or use another compiler.

I am personally interested in the evolving C++ standard for a number of
reasons, but reason #1 is that I'm interested in learning how to make it
work best for me. Implicit conversions are dangerous, so I avoid them.
What else needs to be said?

>But you don't omit them because they are "something to be
>avoided."  You weigh the consequences and decide whether to use
>them.  So, do you have a specific reason for excluding his
>conversion operator?

Same reason you might exclude conversion operators for other classes: It
hides potentially dangerous code.

>So, the rules for determining what should and shouldn't be
>included in the standard is what is important to you?  Don't you
>see that you're both saying the same thing?  "I think its common
>and important so it should have been in the standard."  "Well, I
>don't use it much, so I think they were right to leave it out."

Of course, both of us are I suppose loudly proclaiming our opinions in a
forum perhaps read by those who do the real standardization work. I am
already aware of that. But we are not both saying the same thing in that
he is presenting an opinion that I disagree with. That's all.

>auto_ptr is less obvious since there are so many ways to
>implement it, and so many things it could do.  What works for
>one won't necessarily work for another.  What is sufficient for
>one isn't necessarily sufficient for another.  However, since
>auto_ptr is a class, you can derive from it to add functionality
>you see as necessary.  You can also choose to scrap auto_ptr and
>implement your own.  Either way, the standard has provided
>commonality and has allowed you to extend or replace its
>behavior, as you see fit.

I am aware of this. I don't understand why you're telling me this or
lecturing me on the standardization effort. Have I unknowingly presented
some sort of opinion that indicated that I thought that the people
involved in the C++ standard are idiots or something?
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: "Paul J. Lucas" <pjl@ptolemy-ethernet.arc.nasa.gov>
Date: 1996/05/15
Raw View
 The standard template class auto_ptr is a useful class -- I've
 independently written something very similar.  But, why doesn't
 auto_ptr go a little farther to be more useful and complete?
 Specifically, why doesn't it contain:

 1.
  auto_ptr<T>& operator=( T *p ) {
   reset( p );
   return *this;
  }

    Doesn't this eliminate a temporary by allowing an ordinary
    pointer to be assigned to an auto_ptr directly?

 2.
  operator T*() const { return get(); }

  This makes the following code legal:

   auto_ptr<int> ai;
   int *p = ai;  // illegal otherwise

 3.
  typedef T value_type;

    This allows you to get at the type so you can write totally
    paramaterized functions because you can declare an instance
    of the type to which an auto_ptr points.

 4. For my set of pointer classes, there was a base pointer
    class:

  template< class T > comp_ptr {
  public:
   // similar members to auto_ptr, but without the
   // managerial semantics
  };

  template< class T > bool
  operator==( comp_ptr<T> const &a, comp_ptr<T> const &b ) {
   return *a == *b;
  }

  // ...and so on for the other relational operators

    This allows comp_ptr (or "comparable pointers") to be used
    in container classes and have them organized by the objects
    pointed to rather than the (meaningless) values of the
    pointers themselves.  I then can see no reason why an
    auto_ptr couldn't be derived from a comp_ptr:

  template< class T > class auto_ptr : public comp_ptr< T > {
  public:
   // ...
  }

 5. There can also be a clone_ptr class:

  template< class T > class clone_ptr : public comp_ptr< T > {
  public:
   clone_ptr( clone_ptr<T> &r ) :
    comp_ptr<T>( r.get() ? r.get()->clone() : 0 )
   {
   }
   clone_ptr<T>& operator=( clone_ptr<T> const &r ) {
    reset( get() ? get()->clone() : 0 );
    return *this;
   }
   // ...
  }

    A clone_ptr has the following sementics:
    - copying clones the object pointed to
    - assignment deletes the old object and then does a copy
    - deletion destroys the object pointed to

    The only prerequisite is that the class T have a (virtual)
    member function clone:

  virtual T* clone() const;

    That copies (copy constructs) itself -- not a large
    imposition.

    A clone_ptr is useful for data structures such as a symbol
    table whereby a symbol may be of a type T or any type derived
    from T depending on the type of symbol it is.  Copying a
    symbol table using clone_ptrs is then easy.

 Comments?

 - Paul J. Lucas
   NASA Ames Research Center  Caelum Research Corporation
   Moffett Field, California  Mountain View, California



[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Nathan Myers <ncm@cantrip.org>
Date: 1996/05/16
Raw View
Paul J. Lucas wrote:
>
>         The standard template class auto_ptr is a useful class -- I've
>         independently written something very similar.  But, why doesn't
>         auto_ptr go a little farther to be more useful and complete?
>         Specifically, why doesn't it contain:
>
>         1.
>                 auto_ptr<T>& operator=( T *p ) {
>                         reset( p );
>                         return *this;
>                 }
>
>            Doesn't this eliminate a temporary by allowing an ordinary
>            pointer to be assigned to an auto_ptr directly?

auto_ptr<> is implemented inline, so temporaries don't matter -- they
can be optimized away.  Also, this hides the conversion, a bad thing
when the two types are not actually interchangeable.

>         2.
>                 operator T*() const { return get(); }
>
>                 This makes the following code legal:
>
>                         auto_ptr<int> ai;
>                         int *p = ai;            // illegal otherwise

Automatic conversions are generally a nightmare.  This conversion
would allow ordinary pointers to leak out invisibly.

>         3.
>                 typedef T value_type;
>
>            This allows you to get at the type so you can write totally
>            paramaterized functions because you can declare an instance
>            of the type to which an auto_ptr points.

This has been added (though it's called "element_type").

>         4. For my set of pointer classes, there was a base pointer
>            class:
>
>                 template< class T > comp_ptr {
>                 public:
>                         // similar members to auto_ptr, but without the
>                         // managerial semantics
>                 };
>
>                 template< class T > bool
>                 operator==( comp_ptr<T> const &a, comp_ptr<T> const &b ) {
>                         return *a == *b;
>                 }
>
>                 // ...and so on for the other relational operators
>
>            This allows comp_ptr (or "comparable pointers") to be used
>            in container classes and have them organized by the objects
>            pointed to rather than the (meaningless) values of the
>            pointers themselves.  I then can see no reason why an
>            auto_ptr couldn't be derived from a comp_ptr:
>
>                 template< class T > class auto_ptr : public comp_ptr< T > {
>                 public:
>                         // ...
>                 }

Sorry, I don't see what good it does to derive from comp_ptr.  If we
(always) wanted these semantics we could put them in auto_ptr directly,
or (better, IMHO) use a comparison object passed to the container.

>         5. There can also be a clone_ptr class:
>
>                 template< class T > class clone_ptr : public comp_ptr< T > {
>                 public:
>                         clone_ptr( clone_ptr<T> &r ) :
>                                comp_ptr<T>( r.get() ? r.get()->clone() : 0 )
>                         {
>                         }
>                         clone_ptr<T>& operator=( clone_ptr<T> const &r ) {
>                                 reset( get() ? get()->clone() : 0 );
>                                 return *this;
>                         }
>                         // ...
>                 }
>
>            A clone_ptr has the following sementics:
>            - copying clones the object pointed to
>            - assignment deletes the old object and then does a copy
>            - deletion destroys the object pointed to
>
>            The only prerequisite is that the class T have a (virtual)
>            member function clone:
>
>                 virtual T* clone() const;
>
>            That copies (copy constructs) itself -- not a large
>            imposition.
>
>            A clone_ptr is useful for data structures such as a symbol
>            table whereby a symbol may be of a type T or any type derived
>            from T depending on the type of symbol it is.  Copying a
>            symbol table using clone_ptrs is then easy.

This could be useful.  The criterion for inclusion in the standard wasn't
whether something might be useful, but whether it was (somehow) necessary.
Many committee members believed auto_ptr was necessary and (just) sufficient.

If you start listing things that could be put in because they might
be useful, it is hard to know when (if ever) you will finish.

Nathan Myers
ncm@cantrip.org
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: willer@carolian.com (Steve Willer)
Date: 1996/05/17
Raw View
pjl@ptolemy-ethernet.arc.nasa.gov (Paul J. Lucas) wrote:

>>>         1.
>>>                 auto_ptr<T>& operator=( T *p ) {
>>>                         reset( p );
>>>                         return *this;
>>>                 }
>>>
> Could you please exaborate on what you mean by "this hides the
> conversion."  Hides _what_ conversion?  Obviously, it's being
> converted from a built-in pointer to an anto_ptr, so what
> conversion are you talking about?

  auto_ptr<int> a = new int(getavaluefora());
  int *b = new int(getavalueforb());
  a = b;          // oops! I meant "*a = *b"!
  delete b;

This code would generate a run-time error, which might not show up until
it's at your customer's site. Without the constructor mentioned above,
there would be no temporaries created, so there would therefore be no
opportunity for a compiler to even warn you about this problem.

My compiler warns me about the creation of temporaries (like if you give
a "char*" to a function that expects a "const string&"), and I deeply
appreciate this feature. It gives me the opportunity to find out errors
like the one above. Your change to auto_ptr removes the opportunity to
find these errors and gives a negligible gain.

>>>         2.
>>>                 operator T*() const { return get(); }

>>Automatic conversions are generally a nightmare.  This conversion
>>would allow ordinary pointers to leak out invisibly.
>
> No, they allow ordinary pointers to receive the value of an
> auto_ptr.  There is no "leak" here: "leak" usually means that an
> object is allocated, but never deallocated.  Assignment to a
> built-in pointer does not cause a memory leak.

User-defined conversion operators are pretty universally accepted as
something to be avoided if at all possible. That's why string doesn't
have an "operator const char *". I would suggest you run to the store
and buy Scott Meyers's two books, "Effective C++" and "More Effective
C++". This issue is dealt with in item #5 of the second book: "Be wary
of user-defined conversion functions".

>>or (better, IMHO) use a comparison object passed to the container.
>
> Example, please.

Take a look at the STL:

  set<myclass,comp_myclass>;

This uses the "comp_myclass" class, with "bool operator(const
myclass&,const myclass&)()" declared within it, instead of making use of
an "operator<()" within myclass.

> Why was it considered necessary?  Necessary for what?  Where
> else in the standard library is auto_ptr used such that it is
> necessary to have it?

The big reason for the class was exception safety. And it's as necessary
as a string or the STL: It does a very good job of promoting good
programming practice and clean code by giving very clear, clean,
minimalist tools to every programmer. That, in my mind, is necessary.

> Copying data structures containing heterogeneous objects is a
> fairly common thing to do in OO programs.  A standard way of
> doing it could be deemed necessary.

Perhaps it would have been nice to have this ability, but it doesn't
bother me overly. First of all, it is _not_ as important or necessary to
the language as the auto_ptr. Second of all, it would take a very short
time to make up a pointer that would work for heterogeneous objects in a
container library such as the STL. Why not just spend the time and write
your own?
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: pjl@ptolemy-ethernet.arc.nasa.gov (Paul J. Lucas)
Date: 1996/05/17
Raw View
In <319A5B70.6A82948C@cantrip.org> Nathan Myers <ncm@cantrip.org> writes:

>Paul J. Lucas wrote:
>>
>>         The standard template class auto_ptr is a useful class -- I've
>>         independently written something very similar.  But, why doesn't
>>         auto_ptr go a little farther to be more useful and complete?
>>         Specifically, why doesn't it contain:
>>
>>         1.
>>                 auto_ptr<T>& operator=( T *p ) {
>>                         reset( p );
>>                         return *this;
>>                 }
>>
>>            Doesn't this eliminate a temporary by allowing an ordinary
>>            pointer to be assigned to an auto_ptr directly?

>auto_ptr<> is implemented inline, so temporaries don't matter -- they
>can be optimized away.

 Why rely on compiler vendors to do the right thing?

>Also, this hides the conversion, a bad thing when the two types are not
>actually interchangeable.

 Could you please exaborate on what you mean by "this hides the
 conversion."  Hides _what_ conversion?  Obviously, it's being
 converted from a built-in pointer to an anto_ptr, so what
 conversion are you talking about?

>>         2.
>>                 operator T*() const { return get(); }
>>
>>                 This makes the following code legal:
>>
>>                         auto_ptr<int> ai;
>>                         int *p = ai;            // illegal otherwise

>Automatic conversions are generally a nightmare.  This conversion
>would allow ordinary pointers to leak out invisibly.

 No, they allow ordinary pointers to receive the value of an
 auto_ptr.  There is no "leak" here: "leak" usually means that an
 object is allocated, but never deallocated.  Assignment to a
 built-in pointer does not cause a memory leak.

 I thought the _point_ of having simple C++ classes was so that
 they behave as close as possible to built-in types where
 appropriate.  Given that the above _specific_ conversion does
 no harm as far as I can see, ignoring the fact that (you think)
 automatic conversions are generally a nightmare, I see no
 reason to make code syntactically ugly:

  int *p = ai.get();  // why??

>>         3.
>>                 typedef T value_type;
>>
>>            This allows you to get at the type so you can write totally
>>            paramaterized functions because you can declare an instance
>>            of the type to which an auto_ptr points.

>This has been added (though it's called "element_type").

 Then, IMHO, it's not consistent with "value_type" being used
 all over the place in STL containers.  Was this a _conscious_
 decision to make it (annoyingly) different?

>>         4. For my set of pointer classes, there was a base pointer
>>            class:
>>
 [ snip ]
>>
>>            This allows comp_ptr (or "comparable pointers") to be used
>>            in container classes and have them organized by the objects
>>            pointed to rather than the (meaningless) values of the
>>            pointers themselves.  I then can see no reason why an
>>            auto_ptr couldn't be derived from a comp_ptr:
>>
 [ snip ]

>Sorry, I don't see what good it does to derive from comp_ptr.

 OK, but you never commented on the utility of comp_ptr unto
 itself.

>If we (always) wanted these semantics we could put them in auto_ptr directly,

 If you like bigger headers with redundant code, fine.
 Personally, I like the mixin style of inheritance for the
 purposes of functionality.  You have to write the comparison
 operators exactly once.  To me, the inheritance says: "auto_ptr
 has the behavior of comp_ptr" and is thereby self-documenting.

>or (better, IMHO) use a comparison object passed to the container.

 Example, please.

>>         5. There can also be a clone_ptr class:
>>
 [ snip ]

>>            A clone_ptr is useful for data structures such as a symbol
>>            table whereby a symbol may be of a type T or any type derived
>>            from T depending on the type of symbol it is.  Copying a
>>            symbol table using clone_ptrs is then easy.

>This could be useful.  The criterion for inclusion in the standard wasn't
>whether something might be useful, but whether it was (somehow) necessary.
>Many committee members believed auto_ptr was necessary and (just) sufficient.

 Why was it considered necessary?  Necessary for what?  Where
 else in the standard library is auto_ptr used such that it is
 necessary to have it?

>If you start listing things that could be put in because they might
>be useful, it is hard to know when (if ever) you will finish.

 Is every container and every algorithm in STL *necessary*?  If
 you want to be minimalistic about it, everything other than the
 streams library and the RTTI stuff to support that feature of
 C++ isn't *necessary* at all.

 Copying data structures containing heterogeneous objects is a
 fairly common thing to do in OO programs.  A standard way of
 doing it could be deemed necessary.

 - Paul J. Lucas
   NASA Ames Research Center  Caelum Research Corporation
   Moffett Field, California  Mountain View, California
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: lars.farm@nts.mh.se (Lars Farm)
Date: 1996/05/18
Raw View
Paul J. Lucas <pjl@ptolemy-ethernet.arc.nasa.gov> wrote:

[ ... about yet another variation of auto_ptr
      as has many, many before him ... ]

I can't help but wonder what the huge volumes of posts regarding
auto_ptr would have looked like if GC was accepted in the language.

--
Lars Farm, lars.farm@nts.mh.se
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: vandevod@cs.rpi.edu (David Vandevoorde)
Date: 1996/05/18
Raw View
>>>>> "PL" == Paul J Lucas <pjl@ptolemy-ethernet.arc.nasa.gov> writes:
[...]
PL>  I thought the _point_ of having simple C++ classes was so that
PL> they behave as close as possible to built-in types where
PL> appropriate.  Given that the above _specific_ conversion does no
PL> harm as far as I can see, ignoring the fact that (you think)
PL> automatic conversions are generally a nightmare, I see no reason
PL> to make code syntactically ugly:

PL>   int *p = ai.get(); // why??
[...]

I suspect the reason for this is that this operation pulls an
``unprotected'' copy of the encapsulated pointer out of auto_ptr.
This should attract the code-maintainer's attention that the
copy should not be deleted, and may be invalidated by certain
operations on the original auto_ptr.

In fact, I find `get()' redundant. Why not use:

 int* p = ai.operator->(); // ;-) ?

[... Nathan Myers ]
>> This could be useful.  The criterion for inclusion in the standard
>> wasn't whether something might be useful, but whether it was
>> (somehow) necessary.  Many committee members believed auto_ptr was
>> necessary and (just) sufficient.

PL>  Why was it considered necessary?  Necessary for what?  Where
PL> else in the standard library is auto_ptr used such that it is
PL> necessary to have it?
[...]

I have similar feelings. Since Santa Cruz, however there is a (not
necessarily good) argument for putting auto_ptr in the standard:
an implementation can merge the encapsulated bool flag and pointer
in a single word of memory --- that cannot be done portably in C++.

Anyway, auto_ptr seems like small enough a template that if you don't
like it, you write your own or use any other preferred alternative.
As you point out, no other part of the standard library imposes it on
us.

 Daveed
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: arnstein@netcom.com (David Arnstein)
Date: 1996/05/19
Raw View
In article <4nieou$n51@onramp.arc.nasa.gov>,
Paul J. Lucas <pjl@ptolemy-ethernet.arc.nasa.gov> wrote:
>
> Why was it considered necessary?  Necessary for what?  Where
> else in the standard library is auto_ptr used such that it is
> necessary to have it?

To implement exception handling in a "safe" way, you almost have to
follow the strategy that every resource allocation is an object
construction.  Furthermore, the transfer of ownership of any resource
from one part of a program to another has to be handled carefully,
because an exception may occur in the midst of this transfer.

It appears that auto_ptr offers a minimal solution.  Any resource
allocation can be placed in some class constructor, and then objects
of that class can be accessed through auto_ptr.

Perhaps it would be unwise to use auto_ptr as a more versatile "smart
pointer."
--
David Arnstein
arnstein@netcom.com


[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: phalpern@truffle.ultranet.com (Pablo Halpern)
Date: 1996/05/20
Raw View
"Paul J. Lucas" <pjl@ptolemy-ethernet.arc.nasa.gov> wrote:

>
>  template< class T > bool
>  operator==( comp_ptr<T> const &a, comp_ptr<T> const &b ) {
>   return *a == *b;
>  }
>
>  // ...and so on for the other relational operators
>
>    This allows comp_ptr (or "comparable pointers") to be used
>    in container classes and have them organized by the objects
>    pointed to rather than the (meaningless) values of the
>    pointers themselves.  I then can see no reason why an
>    auto_ptr couldn't be derived from a comp_ptr:

If you want a pointer class whose behavior hides the fact that it is a
pointer, then I suggest you don't use the abreviation "ptr" in your
class name. auto_ptr<> has pointer-like semantics that, IMHO, shouldn't
be disguised. Providing an operator==() for auto_ptr would give the
mistaken impression that the pointers are being compared. Since the
whole point of auto_ptr is that there is only one pointer to a given
object, two auto_ptrs should never compare equal unless they were both
NULL.

-------------------------------------------------------------
Pablo Halpern                   phalpern@truffle.ultranet.com

I am self-employed. Therefore, my opinions *do* represent
those of my employer.
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]