Topic: Implementing auto_ptr + type of operator->*


Author: schuenem@informatik.tu-muenchen.de (Ulf Schuenemann)
Date: 1995/09/15
Raw View
In article <9509080952.AA15973@jodium.cs.few.eur.nl>, Rogier Goossens <goos=
sens@cs.few.eur.nl> writes:
|>=20
|> I have another, related question:
|>=20
|> For a 'pointer' type to be complete, it seems to me it needs an 'operato=
r ->*'
|> as well.
|>=20
|> How would such an operator be declared for a pointer<C> class ?
|>=20
|> One possibility is:
|>=20
|>     template<class C>
|>     class pointer {
|>  public:
|>  template<class TMC>  // TMC : type of member of class C
|>  TMC &pointer<C>::operator ->*(TMC *cmp);    // cmp: C member pointer
|>  }
[..]
|> The semantics would then have to be something like:
|>=20
|>     pointer<myclass> p;
|>     ...
|>     p->*memberptr;     <-->  p->(p.operator->*(memberptr));
|>     p->*methodptr(...);     <-->  p->(p.operator->*(methodptr))(...);
[..]
|> To resume:
|> - Is such a declaration for operator->* possible at all, and if so, is
|>   the declaration above correct.

AFAIK it is possible. ->* is overloadable (13.5[over.oper],3).

5.5[expr.mprt.oper],3:
  ... second operand, which shall be of type "ptr to mem of T" to it's
                                              ^^^^^^^^^^^^^^^
  first operand, which shall be of type ptr to T ...
  The result is ... of the type specified by the second argument.

Instead of template parameter 'TMC: type of member of class C',
I'd suggest 'TPMC: type of ptr to member of class C'.
Then you can forget about TMC& and TMC*.

|> - If it is possible, are 'my' semantics of operator->* correct.

Using operator-> and operator->* to describe semantics of userdefined
operator->* confuses me. I prefere an implementation that is based
on the non-overloadable operator.*:

template<class C, class TPMC>           // TPMC: type of ptr to member of C
TPMC auto_ptr<C>::operator->*(TPMC pmc) //  pmc: a ptr to member of C
{
 return (*get()).*pmc;
}

[ Is this the correct syntax for template members of a template class? ]

For orthogonality with (the not so old feature of) memberpointers
(that can be used on objects by .* and on built-in pointers by ->*)
I would appreciate if operator->* would be a standard part of auto_ptr.

Ulf Schuenemann

--------------------------------------------------------------------
  ,_.   Ulf Sch=FCnemann
 #,  \  Fakult=E4t f=FCr Informatik, Technische Universit=E4t M=FCnchen, Ge=
rmany.
  |   > email: schuenem@informatik.tu-muenchen.de
  v==-<  WWW:   http://hphalle2.informatik.tu-muenchen.de/~schuenem/
        ...there is only one way to "skin a C+@"...:)  -- Jim Fleming

[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]






Author: Rogier Goossens <goossens@cs.few.eur.nl>
Date: 1995/09/08
Raw View
> I've been trying to implement the auto_ptr template of section 20.4.5 of
> the draft standard, and, much to my surprise, this seems to be a compiler
> buster.  Borland 4.51, MetaWare 3.3, and g++ 2.6.3 all generate errors
> either during compilation or linking.

With g++ 2.7.0 I got:

try.cc: In function `int main()':
try.cc:15: cannot convert type `Foo *' to type `auto_ptr<Foo> &'
auto_ptr.h:5: in passing argument 1 of `auto_ptr<Foo>::auto_ptr(auto_ptr<Foo> &)'
ptr_try.cc:15: in base initialization for class `auto_ptr<Foo>'

Line 15 is the line p1 is defined in.
Although I do not quite understand why, I have been told this behavior is
correct. It is a result of the constructor being explicit.
After changing that line to :

    auto_ptr<Foo> p1(new Foo(1,2,10));

Your code compiles OK and outputs:

    1 2 10


I have two more remarks:

>   template<class T>
>   inline void operator=(auto_ptr<T>& rhs)
>   { ptr = rhs.release; }

Don't forget to delete the previous object ptr pointed to.

>   template<class T>
>   inline auto_ptr<T>::~auto_ptr() { delete ptr; }

I'm not sure whether 'delete ptr' is legal when ptr==NULL. If not,
you'd better check.

 [There is no need to check.  `delete ptr' is guaranteed to have
 no effect when ptr==NULL.  -fjh (moderator).]

I have another, related question:

For a 'pointer' type to be complete, it seems to me it needs an 'operator ->*'
as well.

How would such an operator be declared for a pointer<C> class ?

One possibility is:

    template<class C>
    class pointer {
 public:
 template<class TMC>  // TMC : type of member of class C
 TMC &pointer<C>::operator ->*(TMC *cmp);    // cmp: C member pointer
 }

This looks like the declaration from section 13.6.11 of the C++ draft
standard :

    CV12 T& operator->*(CV1 C*, CV2 T C::*);

which holds for non-class types.
(CV* are 'cv-qualifier-seqs', T is a complete object or function type,
and C is a class type.)


The semantics would then have to be something like:

    pointer<myclass> p;
    ...
    p->*memberptr;     <-->  p->(p.operator->*(memberptr));
    p->*methodptr(...);     <-->  p->(p.operator->*(methodptr))(...);

The alternative:

    p->*memberptr;     <--> p.operator->*(memberptr);

only works for non-method member pointers: operator->* retuns a member
reference which allows it to compute the actual member that should be
used/invoked.  For pointers to non-method members, operator->* could also
compute the actual object to use (like operator-> does), and return a
reference to the requested member of that object (1).  For method pointers,
this is not possible, as it doesn't know which arguments to use in the
invocation.

(1): This may not always be legal though. It may require a conversion from
     member pointer to regular pointer (e.g. int C::* -> int *), which is not
     allowed as far as I know.


Although the draft standard does mention how a user-defined operator-> works
(in section 13.5.6), it does not mention anything about a user-defined
operator->*. The only thing I found was is section 13.6.11 (see above), which
only applies to built-in operators.


To resume:
- Is such a declaration for operator->* possible at all, and if so, is
  the declaration above correct.
- If it is not possible, can a 'real' pointer class be written at all ?
- If it is possible, are 'my' semantics of operator->* correct.


Rogier
goossens@cs.few.eur.nl
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: kuehl@horn.rz.uni-konstanz.de (Dietmar Kuehl)
Date: 1995/09/09
Raw View
Hi,
Rogier Goossens (goossens@cs.few.eur.nl) wrote:
: I have two more remarks:
:
: >   template<class T>
: >   inline void operator=(auto_ptr<T>& rhs)
: >   { ptr = rhs.release; }
:
: Don't forget to delete the previous object ptr pointed to.

The standard doesn't say something about deleting the old pointer!  My
interpretation is this: auto_ptr is not supposed to delete all pointers
but only the one it is holding when it gets destructed.  This semantic
is indeed useful if it is possible that an exception is thrown while
nothing else takes care of the allocated object or some memory should
be released when exiting a function. In the meantime the programmer has
still to care for the pointer if it is replaced.

dk
--
http://www.informatik.uni-konstanz.de/~kuehl
dietmar.kuehl@uni-konstanz.de
I am a realistic optimist - that's why I appear to be slightly pessimistic
---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: kanze <kanze@lts.sel.alcatel.de>
Date: 1995/09/11
Raw View
In article <42sf4t$9im@eurybia.rz.uni-konstanz.de>
kuehl@horn.rz.uni-konstanz.de (Dietmar Kuehl) writes:

|> Rogier Goossens (goossens@cs.few.eur.nl) wrote:
|> : I have two more remarks:
|> :
|> : >   template<class T>
|> : >   inline void operator=(auto_ptr<T>& rhs)
|> : >   { ptr = rhs.release; }
|> :
|> : Don't forget to delete the previous object ptr pointed to.

|> The standard doesn't say something about deleting the old pointer!  My
|> interpretation is this: auto_ptr is not supposed to delete all pointers
|> but only the one it is holding when it gets destructed.  This semantic
|> is indeed useful if it is possible that an exception is thrown while
|> nothing else takes care of the allocated object or some memory should
|> be released when exiting a function. In the meantime the programmer has
|> still to care for the pointer if it is replaced.

The draft standard does say that the semantics of assignment include a
call to reset.  It doesn't say anything about the semantics of reset,
but the original proposal did.

>From 94-0202R1/N0289R1:

   Semantics
   ---------
   An auto_ptr<X> object holds a pointer to an object of class X, presented
   here as X* px. In the following table: p and px are pointers to an object
   of class X or a class derived from X for which delete(X*) is defined and
   accessible, or else null; d is an auto_ptr<D> where D is X or a class
   derived from X; a is an auto_ptr<X>; and m is a member of X.

      Expression           Value             Effect
      ------------------   ---------------   ---------------------
      auto_ptr<X> a(p)                       a.px = p
      auto_ptr<X> a(d)                       a.px = d.release()
      a.~auto_ptr<X>()                       delete a.px
      a = d                reference to a    a.reset(d.release())
      *a                   *a.px
      a->m                 a.px->m
      a.get()              a.px
      a.release()          a.px              a.px = 0
      a.reset(p)                             delete a.px, a.px = p

IMHO, these are the only semantics which make sense; if I *don't*
delete the old pointer in assignment, who will?
--

James Kanze         Tel.: (+33) 88 14 49 00        email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs-Bourgeois, F-67000 Strasbourg, France
Conseils en informatique industrielle --
                              -- Beratung in industrieller Datenverarbeitung



---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]