Topic: Why 'operator->' requires return type to be a pointer?


Author: "Samuel Schulman" <s.schulman@berlin.de>
Date: Mon, 18 Jun 2001 18:15:37 GMT
Raw View
>
>"Daniel Frey" <daniel.frey@aixigo.de> wrote in message
news:3B2619B0.21B1CABD@aixigo.de...
>Hello,
>
>Consider the following code:
>
>
>
>template< typename T > class oid // 'pointer' to a database object
>{
>   ...
>
>   T asObject() const // OK
>   {
>      return T( *this );
>   }
>
>   T operator->() const // Not OK, T must be T*
>   {
>      return T( *this );
>   }
>
>   ...
>};
>
>
>  oid< X > x;
>
>  cout << x.asObject().name(); // Works, but looks ugly.
>  cout << x->name(); // Doesn't work.
>
>  cout << x.asObject().parent().asObject().owner().asObject().name(); //
>Ouch...
>  cout << x->parent()->owner()->name(); // Yeah!
>
>
>
>Why is operator-> required (AFAIK) to return a pointer? Is there any
>good reason I can't see? Was it considered to change (enhance) the
>standard on that point? This shouldn't even break any existing code as
>it only allows what's currently illegal.
>
>Regards, Daniel
>
>--
>Daniel Frey
>

The standard does not require the operator to return type of pointer-to-T.
As with the other operators, you usually want an operator, to behave like
its
built-in counterpart.
The operator->() is used in other cases as well, where he does not return
pointer-to-T but returns class type.
But you should be aware of what you really want, and what the tradeoffs are.

In this line:

cout << x->parent()->owner()->name(); // Yeah! (are you sure:))

you will have three temporary objects created and destroyed, which means you
will have
three times the constructor executed and three times the destructor
executed, this can get
expensive.
Therefore(as usual) be sure what you need, and what you will pay for it, in
the end .

 - Samuel

---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "James Kuyper Jr." <kuyper@wizard.net>
Date: Thu, 14 Jun 2001 04:30:07 GMT
Raw View
Daniel Frey wrote:
>
> "James Kuyper Jr." wrote:
> >
> > Daniel Frey wrote:
> > >
> > > Hello,
> > >
> > > Consider the following code:
> > >
> > > template< typename T > class oid // 'pointer' to a database object
> > > {
> > >    ...
> > >
> > >    T asObject() const // OK
> > >    {
> > >       return T( *this );
> > >    }
> > >
> > >    T operator->() const // Not OK, T must be T*
> > >    {
> > >       return T( *this );
> > >    }
> > >
> > >    ...
> > > };
> > >
> > >   oid< X > x;
> > >
> > >   cout << x.asObject().name(); // Works, but looks ugly.
> > >   cout << x->name(); // Doesn't work.
> >
> > Well, it would work if you returned a T*, which might give you a hint as
> > to why it's required.
>
> I can't follow you on that. If I return a T*, I would have a memory
> leak. asObject() return a temporary object, .name() is called for this
> object and it is destructed after that. I cannot do this with
> operator->, but I don't understand why. IMHO it should be possible to
> return T instead of T* here.

The main purpose of operator->() is to be invoked as a result of the
evaluation of expressions like:

 x->name()

When it is invoked that way, it's invoked as if in the following
context:

 (x.operator->())->name()

Given that this is what operator->() means, it's not a good idea for it
to return a value of any type that can't legally appear in that context.
For instance, your code essentially is equivalent to

 (T(*this))->name()

That just plain doesn't work. Therefore, you can only use operator->()
if you have a pointer that you can release, unless you're willing to use
a round-about method such as the one that Marco Manfredini suggested.

---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "Daniel Frey" <d.frey@gmx.de>
Date: Thu, 14 Jun 2001 13:12:54 GMT
Raw View
In article <3B280393.F2902C59@wizard.net>, "James Kuyper Jr."
<kuyper@wizard.net> wrote:

> The main purpose of operator->() is to be invoked as a result of the
> evaluation of expressions like:
>
>  x->name()
>
> When it is invoked that way, it's invoked as if in the following
> context:
>
>  (x.operator->())->name()

I see. I understand. (I hope so :) But if the definition would be

   (x.operator->()).name()

you could return a reference or (as in my case) a temporary. This seems
better to me as it doesn't require additional restrictions or
work-arounds. And returning a reference means to me that I cannot return a
null-pointer.

But I guess we now enter the C-compatibility-backyards of C++, right?
Changing the above means breaking compatibility... probably a suggestion
for C++Ox.

Thanks for the explanation.

Regards, Daniel

---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Daniel Frey <daniel.frey@aixigo.de>
Date: Tue, 12 Jun 2001 19:12:37 GMT
Raw View
Hello,

Consider the following code:



template< typename T > class oid // 'pointer' to a database object
{
   ...

   T asObject() const // OK
   {
      return T( *this );
   }

   T operator->() const // Not OK, T must be T*
   {
      return T( *this );
   }

   ...
};


  oid< X > x;

  cout << x.asObject().name(); // Works, but looks ugly.
  cout << x->name(); // Doesn't work.

  cout << x.asObject().parent().asObject().owner().asObject().name(); //
Ouch...
  cout << x->parent()->owner()->name(); // Yeah!



Why is operator-> required (AFAIK) to return a pointer? Is there any
good reason I can't see? Was it considered to change (enhance) the
standard on that point? This shouldn't even break any existing code as
it only allows what's currently illegal.

Regards, Daniel

--
Daniel Frey

aixigo AG - financial training, research and technology
Schlo=DF-Rahe-Stra=DFe 15, 52072 Aachen, Germany
fon: +49 (0)241 936737-42, fax: +49 (0)241 936737-99
eMail: daniel.frey@aixigo.de, web: http://www.aixigo.de

---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: "James Kuyper Jr." <kuyper@wizard.net>
Date: Wed, 13 Jun 2001 01:12:37 GMT
Raw View
Daniel Frey wrote:
>
> Hello,
>
> Consider the following code:
>
> template< typename T > class oid // 'pointer' to a database object
> {
>    ...
>
>    T asObject() const // OK
>    {
>       return T( *this );
>    }
>
>    T operator->() const // Not OK, T must be T*
>    {
>       return T( *this );
>    }
>
>    ...
> };
>
>   oid< X > x;
>
>   cout << x.asObject().name(); // Works, but looks ugly.
>   cout << x->name(); // Doesn't work.

Well, it would work if you returned a T*, which might give you a hint as
to why it's required.

---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: marco@technoboredom.net (Marco Manfredini)
Date: Wed, 13 Jun 2001 12:23:13 GMT
Raw View
Daniel Frey <daniel.frey@aixigo.de> wrote in
news:3B2619B0.21B1CABD@aixigo.de:

>
> Why is operator-> required (AFAIK) to return a pointer?

It isn't. It is required to return a something which has "->" defined,
either intrinsic or as operator.

Example:
class A
{
public:
     A* operator -> () { return this; }
  void foo() { cout << "Hello" << endl; }
};

class B
{
public:
     A operator -> () { return A(); }
};

int main()
{
 B b;
 b->foo(); // B::operator-> and *then* A::operator-> !!
}

Hope this helps.

--
Marco

---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Daniel Frey <daniel.frey@aixigo.de>
Date: Wed, 13 Jun 2001 12:24:41 GMT
Raw View
"James Kuyper Jr." wrote:
>=20
> Daniel Frey wrote:
> >
> > Hello,
> >
> > Consider the following code:
> >
> > template< typename T > class oid // 'pointer' to a database object
> > {
> >    ...
> >
> >    T asObject() const // OK
> >    {
> >       return T( *this );
> >    }
> >
> >    T operator->() const // Not OK, T must be T*
> >    {
> >       return T( *this );
> >    }
> >
> >    ...
> > };
> >
> >   oid< X > x;
> >
> >   cout << x.asObject().name(); // Works, but looks ugly.
> >   cout << x->name(); // Doesn't work.
>=20
> Well, it would work if you returned a T*, which might give you a hint a=
s
> to why it's required.

I can't follow you on that. If I return a T*, I would have a memory
leak. asObject() return a temporary object, .name() is called for this
object and it is destructed after that. I cannot do this with
operator->, but I don't understand why. IMHO it should be possible to
return T instead of T* here.

Probably I should note that 'oid' in the above example is a 'pointer' to
a database object. If I call T( *this ), the object is loaded from the
database, so I don't have an object I can return a real pointer to, I
need a temporary object. The alternative would be to return a
reference-counted pointer, but this is still not allowed as I cannot
write

   smart_pointer< T > operator->() const { ... }

and as I notice an increasing use of smart pointers (including OIDs =3D
pointers to persistent objects) I wondered if the requirement for
operator-> is still appropriate. If you know the reason, please explain
it to me as I still don't get it :)

Regards, Daniel

--
Daniel Frey

aixigo AG - financial training, research and technology
Schlo=DF-Rahe-Stra=DFe 15, 52072 Aachen, Germany
fon: +49 (0)241 936737-42, fax: +49 (0)241 936737-99
eMail: daniel.frey@aixigo.de, web: http://www.aixigo.de

---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]





Author: Daniel Frey <daniel.frey@aixigo.de>
Date: Wed, 13 Jun 2001 12:50:03 GMT
Raw View
Marco Manfredini wrote:
>=20
> Daniel Frey <daniel.frey@aixigo.de> wrote in
> news:3B2619B0.21B1CABD@aixigo.de:
>=20
> >
> > Why is operator-> required (AFAIK) to return a pointer?
>=20
> It isn't. It is required to return a something which has "->" defined,
> either intrinsic or as operator.
>=20
> Example:
> class A
> {
> public:
>         A* operator -> () { return this; }
>                 void foo() { cout << "Hello" << endl; }
> };
>=20
> class B
> {
> public:
>         A operator -> () { return A(); }
> };
>=20
> int main()
> {
>         B b;
>         b->foo(); // B::operator-> and *then* A::operator-> !!
> }
>=20
> Hope this helps.

It does. Thanks. (Though I still don't understand the reason why this
'workaround' is required by the standard :)

Regards, Daniel

--
Daniel Frey

aixigo AG - financial training, research and technology
Schlo=DF-Rahe-Stra=DFe 15, 52072 Aachen, Germany
fon: +49 (0)241 936737-42, fax: +49 (0)241 936737-99
eMail: daniel.frey@aixigo.de, web: http://www.aixigo.de

---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html                ]