Topic: Overloding by return value


Author: meixner@rbg.informatik.tu-darmstadt.de (Matthias Meixner)
Date: 2000/06/09
Raw View
Stephen Cleary (scleary@jerviswebb.com) wrote:

[...]

)
) Implementation difficulty.  From "The C++ Programming Language", 3rd
) ed., by Stroustrup, [7.4.1]: "Return types are not considered in
) overload resolution.  The reason is to keep resolution for an
) individual operator or function call context-independent."
)
) That is, it makes implementing a compiler easier.  Return value
) overloading is technically possible, but would make the overload
) resolution much more complicated, possibly having to work on the entire

That's not really the case. In form of user defined conversions you
already have overloading by return value and you can use this
to implement overloading by return value (simply write a wrapper,
that collects the function parameters and pack that into an
object. Move the real functionality to the conversion function.)

) full-expression in order to get enough context.  Consider:
)   int g();
)   float g();
)   int f(int x);
)   int f(bool x);
)   float f(float x);
)
)   int tmp = f(g());
)
) The call to g() is not resolved until the call to f() is resolved.  But
) if parameters also participate in function overloading, then f() has to
) have "tentative resolutions" based on its return type, then choose
) "solid resolutions" based on its parameters.  Then do this at each
) level in a full-expression.  In essence, it just gets too complicated.
)
) Without return value overloading, we can just look at a single function
) call "f(x)" and *know* what function it calls, no matter what context
) it is in.

For whom is it too complicated, the compiler or a human reading the source.
Without doubt you could implement some set of overloading rules in a compiler,
however code that uses this technique would be really hard to read. So it
is probably a good idea not to have overloading by return value for normal
(member) functions.

- Matthias Meixner

--
Matthias Meixner                   meixner@rbg.informatik.tu-darmstadt.de
Technische Universit   t Darmstadt
Rechnerbetriebsgruppe                          Telefon (+49) 6151 16 6670
Wilhelminenstra   e 7, D-64283 Darmstadt, Germany    Fax (+49) 6151 16 4701


---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Bruno Gustavs" <GustavsB@ch.sibt.com>
Date: 2000/06/09
Raw View
"Stephen Cleary" <scleary@jerviswebb.com> wrote in message
news:8hma00$gjf$1@nnrp1.deja.com...
> Implementation difficulty.  From "The C++ Programming Language", 3rd
> ed., by Stroustrup, [7.4.1]: "Return types are not considered in
> overload resolution.  The reason is to keep resolution for an
> individual operator or function call context-independent."
>
> That is, it makes implementing a compiler easier.  Return value
> overloading is technically possible, but would make the overload
> resolution much more complicated, possibly having to work on the entire
> full-expression in order to get enough context.  Consider:
>   int g();
>   float g();
>   int f(int x);
>   int f(bool x);
>   float f(float x);
>
>   int tmp = f(g());
>
> The call to g() is not resolved until the call to f() is resolved.  But
> if parameters also participate in function overloading, then f() has to
> have "tentative resolutions" based on its return type, then choose
> "solid resolutions" based on its parameters.  Then do this at each
> level in a full-expression.  In essence, it just gets too complicated.
>
> Without return value overloading, we can just look at a single function
> call "f(x)" and *know* what function it calls, no matter what context
> it is in.

Please have a look at the following example from Roland Sch   uble
and me, whitch compiles with gcc 2.95.2:

#include <iostream>

class Base
{
public:
  virtual Base& get_me()
    { cout << "Base& get_me()\n"; return *this; }
};

class Derived : public Base
{
public:
  virtual Derived& get_me()
    { cout << "Derived& get_me()\n"; return *this; }
};

void fun(Derived d)
{
  cout << "I am derived\n";
}

int main()
{
  Base *d = new Derived;
  d->get_me();
  // fun(d->get_me());

  return 0;
}

It really looks like overloading by return value. In fact it is not,
since d->get_me() still returns a Base object reference.

Regards
Bruno Gustavs



---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Steve Clamage <stephen.clamage@sun.com>
Date: 2000/06/09
Raw View
Stephen Cleary wrote:
>
> Implementation difficulty.  From "The C++ Programming Language", 3rd
> ed., by Stroustrup, [7.4.1]: "Return types are not considered in
> overload resolution.  The reason is to keep resolution for an
> individual operator or function call context-independent."
>
> That is, it makes implementing a compiler easier.

Well, yes, but not that much easier.  The current overloading
rules require considerable complexity in the compiler. Overloading
by return type would not make things significantly more difficult
for the compiler.

The more important reason is that it makes it easier for people
to understand a program, and to be more sure of what you will
get when you overload a function.

Even with a complicated expression, you can determine what each
function call will be by looking only at its arguments. If
overloading on return type is involved, the entire expression must
be considered.

Programmers are often unpleasantly surprised by the ambiguity
errors they get when overloading functions.  Overloading on
return type would add to the likelihood of ambiguity.

Given the frequency of questions about which overloaded function
should be called under current rules, and the variety of answers
you sometimes see even from experienced programmers, adding another
dimension of complexity doesn't seem like a good idea.

--
Steve Clamage, stephen.clamage@sun.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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: James Kuyper <kuyper@wizard.net>
Date: 2000/06/09
Raw View
Bruno Gustavs wrote:
>
> "Francis Glassborow" <francis@robinton.demon.co.uk> wrote in message
> news:r5RPSnA+7qP5Ewi3@robinton.demon.co.uk...
> > >Example:
> > >int powII(int, int); float powFI(float, int); float powFF(float, float);
> > >can be replaced by a single (overloaded) name pow.
> >
> > What point are you making?  As the three differ in their parameter
> > types, where is the problem with overloading them?
>
> Sorry, but I feel missunderstood. ...

The reason you feel misunderstood is that you provided a poor example,
and therefore inadvertently provided a counter-argument to your very own
proposal. The examples you gave were completely(!) disambiguated by the
existing capability to overload by the parameter list. It's fairly
commonplace that the most natural design produces exactly that result.
Even when it's not the most natural design, the same effect can often be
achieved deliberately without producing too unnatural a design. As a
result, overloading by return type is less attractive than it might
otherwise seem.

There's also a way to achieve an effect similar to overloading by return
type, though it isn't always applicable. Instead of using the return
value from a function, add an argument to the function which is a
non-const pointer or reference to the location where the result is to be
stored. Obviously, this is not applicable for operator overloads, and
the interface is a bit clumsier than using return types.

I'm not saying that there aren't cases where overloading by return type
wouldn't make some things simpler, but they aren't as common as you
might think. On the other hand, the difficulties are significant:
overload resolution gets significantly more complicated for the compiler
to implement, and for the developer to anticipate. Unexpected overload
resolution is already one of the most common types of problems in C++,
we don't need to make it worse.

> ... The thing, I want to point out is, that
> overloading by parameters is a well known technique in C++ and
> allows you to save names. Similarly, overloading by return
> values could save names. Saving name has nothing to do with
> deep concepts, its just nice. Overloading in conjunction with
> polymorhism in contrast has a deep impact on concepts.

Generic programming benefits significantly from overloading.  Template
functions are themselves an extreme example of overloading. Both
template functions and template classes are made simpler by allowing
them to call overloaded functions. Operator overloads are the best
example, since you can count on them being available even for standard
types. However, it's also useful to document that a given template may
only be instantiated with a type for which a function of a fixed name is
available, overloaded for that type.

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: James Kuyper <kuyper@wizard.net>
Date: 2000/06/09
Raw View
Matthias Meixner wrote:
>
> Stephen Cleary (scleary@jerviswebb.com) wrote:
>
> [...]
>
> )
> ) Implementation difficulty.  From "The C++ Programming Language", 3rd
> ) ed., by Stroustrup, [7.4.1]: "Return types are not considered in
> ) overload resolution.  The reason is to keep resolution for an
> ) individual operator or function call context-independent."
> )
> ) That is, it makes implementing a compiler easier.  Return value
> ) overloading is technically possible, but would make the overload
> ) resolution much more complicated, possibly having to work on the entire
>
> That's not really the case. In form of user defined conversions you
> already have overloading by return value and you can use this
> to implement overloading by return value (simply write a wrapper,
> that collects the function parameters and pack that into an
> object. Move the real functionality to the conversion function.)

Every time you add a conversion constructor or a type conversion
operator to a system, you increase the likelihood of unexpected or
ambiguous conversions.

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Michiel Salters <salters@lucent.com>
Date: 2000/06/10
Raw View
Bruno Gustavs wrote:

> "Francis Glassborow" <francis@robinton.demon.co.uk> wrote in message
> news:r5RPSnA+7qP5Ewi3@robinton.demon.co.uk...
> > >Example:
> > >int powII(int, int); float powFI(float, int); float powFF(float, float);
> > >can be replaced by a single (overloaded) name pow.

> > What point are you making?  As the three differ in their parameter
> > types, where is the problem with overloading them?

> Sorry, but I feel missunderstood. The thing, I want to point out is, that
> overloading by parameters is a well known technique in C++ and
> allows you to save names. Similarly, overloading by return
> values could save names. Saving name has nothing to do with
> deep concepts, its just nice. Overloading in conjunction with
> polymorhism in contrast has a deep impact on concepts.

> Regards
> Bruno Gustavs

The problem is that overload resolution happens within the context
of an expression, like

expr=.....f(sub expr).....

We don't have to evaluate the .... parts to determine which overload of
f to select with the current scheme. This greatly reduces the complexity,
because we only have to determine the subtype of a smaller expression.
With your proposal, we'd have to evaluate the rest of the expression
to determine which f to choose.

Worse, what happens if subexpr itself is overloaded on return type?

Imagine 3 overloaded functions f1, f2 and g:
(And g doesn't return an integer)
int x = g(f1(1),f2(2));
Which f1 and f2 must be chosen would depend on which g is chosen and
vica versa, you have to consider (almost) each combination of f1, f2 and g,
taking into account possible casts etc.

I think that if each function 'i' (i=1..N) in a complex expression has A(i)
overloads than without return overloading the complexity of determining
the correct set of overloads takes O(sum [i=1..N] A(i) ) work. With return
value overloads the work might be O(prod [i=1..N] A(1) ) depending on
the exact structure of subexpressions. The latter is exponential in i, while
the first is linear in i. I guess this was enough reason to not allow
this.

Of course, for your example 'i' can only be one, since the only function
involved is f, and the work in both cases is O(A(1) ).

Michiel Salters

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Mark Williams <markw65@my-deja.com>
Date: 2000/06/10
Raw View
In article <3940F3EA.2DEB29AC@lucent.com>,
  Michiel Salters <salters@lucent.com> wrote:
>
> Worse, what happens if subexpr itself is overloaded on return type?
>
> Imagine 3 overloaded functions f1, f2 and g:
> (And g doesn't return an integer)
> int x = g(f1(1),f2(2));
> Which f1 and f2 must be chosen would depend on which g is chosen and
> vica versa, you have to consider (almost) each combination of f1, f2
and g,
> taking into account possible casts etc.

Which is something the compiler already knows how to do:

class f1 {
public:
 f1(int);

 operator int();
 operator double();
};

class f2 {
public:
 f2(int);

 operator char*();
 operator double();
};

long g(int, double);
long g(double, long);
long g(char*, char*);

int foo()
{
 return g(f1(1), f2(2));
}


-------------
Mark Williams


Sent via Deja.com http://www.deja.com/
Before you buy.

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Stephen Howe" <SPAMGUARDstephen.howe@dial.pipex.co.uk>
Date: 2000/06/10
Raw View
Greg Comeau <comeau@panix.com> wrote in message
news:8hje6r$os$1@panix3.panix.com...
> In article <8hif95$bdj$1@pollux.ip-plus.net>,
> Bruno Gustavs <GustavsB@ch.sibt.com> wrote:
> >Why does c++ not support overloading by return value?
> >i.e. something like
> >
> >class A
> >{
> >public:
> >  float  f();
> >  double f();
> >};
>
> Permit me to respond with some counter-questions:
> * What becomes easier if it's allowed?
> * What techniques in real code would be enhanced by such a capability?
> * What about new problems it creates?

I will bite on this as I have thought the same. Suppose you have two
graphics functions

unsigned long SetPixel(int x, int y);
void SetPixel(int x, int y);

where the first function returns the previous colour of the pixel before it
is set for a graphics cursor and the second function just sets the pixel.
The principal reason for this is speed, as it takes time to "read" a pixel
and intuitive

I would expect a compiler to match the functions for the call

SetPixel(10, 20);                        // 1st function called
oldcolour = SetPixel(10, 20);    // 2nd function called

This to me seems more pleasing to the eye than having to rewrite this in the
form

void SetPixel(int x, int y, long &oldcolour);

In terms of the compiler having to match arguments + return value, the
return value could be treated just like one of the parameters of the
function with it having no more weight than matching on the arguments a
function takes. No return value would be equivalent to matching on a
function with no  return type, i.e. void.

Stephen Howe



---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Peter Chapin <pchapin@sover.net>
Date: 2000/06/10
Raw View
In article <3940F3EA.2DEB29AC@lucent.com>, salters@lucent.com says...

> The problem is that overload resolution happens within the context
> of an expression, like
>
> expr=.....f(sub expr).....
>
> We don't have to evaluate the .... parts to determine which overload of
> f to select with the current scheme. This greatly reduces the complexity,
> because we only have to determine the subtype of a smaller expression.
> With your proposal, we'd have to evaluate the rest of the expression
> to determine which f to choose.

It seems to me that overloading on return type is logically equivalent
to overloading data objects. For example:

void f()
{
  int g();
  double g();

  int x;
  double x;
    // If the compiler can resolve the use of the two g()'s why not the
    // two x's?

}

I quiver with fear when I contemplate the wording in the standard to
describe such a thing. :-)

Peter

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: meixner@rbg.informatik.tu-darmstadt.de (Matthias Meixner)
Date: 2000/06/13
Raw View
James Kuyper (kuyper@wizard.net) wrote:
) Matthias Meixner wrote:
) >
[...]
) >
) > That's not really the case. In form of user defined conversions you
) > already have overloading by return value and you can use this
) > to implement overloading by return value (simply write a wrapper,
) > that collects the function parameters and pack that into an
) > object. Move the real functionality to the conversion function.)
)
) Every time you add a conversion constructor or a type conversion
) operator to a system, you increase the likelihood of unexpected or
) ambiguous conversions.

That's not really true for this case, since you add one additional class
and only conversion functions from this newly added class to existing
classes. So using this technique you cannot add additional ambiguities.

However it is likely that you will see unexpected behaviour, but that
would be the same as with overloading by return type.

- Matthias Meixner

--
Matthias Meixner                   meixner@rbg.informatik.tu-darmstadt.de
Technische Universit   t Darmstadt
Rechnerbetriebsgruppe                          Telefon (+49) 6151 16 6670
Wilhelminenstra   e 7, D-64283 Darmstadt, Germany    Fax (+49) 6151 16 4701


---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: James Kuyper <kuyper@wizard.net>
Date: 2000/06/13
Raw View
Matthias Meixner wrote:
>
> James Kuyper (kuyper@wizard.net) wrote:
> ) Matthias Meixner wrote:
> ) >
> [...]
> ) >
> ) > That's not really the case. In form of user defined conversions you
> ) > already have overloading by return value and you can use this
> ) > to implement overloading by return value (simply write a wrapper,
> ) > that collects the function parameters and pack that into an
> ) > object. Move the real functionality to the conversion function.)
> )
> ) Every time you add a conversion constructor or a type conversion
> ) operator to a system, you increase the likelihood of unexpected or
> ) ambiguous conversions.
>
> That's not really true for this case, since you add one additional class
> and only conversion functions from this newly added class to existing
> classes. So using this technique you cannot add additional ambiguities.

What is the "this case" that you're referring to? You brought in user
defined type conversion operators in general, as an example of how C++
compilers can already handle overloading by return type in a special
case.
I was responding to that comment. I said nothing about adding a new
class, only about adding "a conversion constructor or type conversion
operator to a system". I didn't specify the system at all. I weakened my
statement by calling it only a "likelihood", to cover the possibility
that the system is so simple that no problem results. However, real
systems often have a great many classes, with conversion constructors
and type conversion operators connecting them to other classes, or even
to non-class types. The new conversion constructor or type conversion
operator I'm talking about would have a chance of being ambiguous with
some of the other conversion paths that already exist.

> However it is likely that you will see unexpected behaviour, but that
> would be the same as with overloading by return type.

I'm not arguing about this as alternative to overloading by return type.
I was pointing out a disadvantage of having too many conversion paths.
That problem would become worse if overloading by return type were to
become allowed in a more general context.

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 2000/06/14
Raw View
Francis Glassborow wrote:
>
> In article <8hq2hc$ndo$1@pollux.ip-plus.net>, Bruno Gustavs
> <GustavsB@ch.sibt.com> writes
> >Sorry, but I feel missunderstood. The thing, I want to point out is, that
> >overloading by parameters is a well known technique in C++ and
> >allows you to save names.
>
> That is a view sometimes put forward but it is not one with which I
> would agree. Overloading is to allow the provision of alternative ways
> to achieve the same result.  That is, an overload set should all do the
> same thing and only diver in that the require different data.  If they
> do the same thing then it would be illogical for them to return
> different types unless that difference directly relates to one of the
> parameter types.  For example, taking a square root is a concept where
> the result type logically depends on the  input type. Indeed, if it were
> not that the computation method depends on the input type, square root
> would be an ideal candidate for a function template.) We might consider
> overloading as a special form of generic programming in which we do not
> use a template because all the cases would be specialisations.

As one example where overloading on the return value would make
sense, imagine a function returning pi:

float pi();
double pi();
long double pi();
my_float pi();     // very high precision float class

my_float foo = pi(); // uses last version

Of course, such examples are rare, and in this case, one
could just write:

struct pi_t
{
  operator float();
  operator double();
  operator long double();
  operator my_float();
} pi;

and then use the (even more natural) syntax:

my_float foo = pi;

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: meixner@rbg.informatik.tu-darmstadt.de (Matthias Meixner)
Date: 2000/06/14
Raw View
James Kuyper (kuyper@wizard.net) wrote:
) Matthias Meixner wrote:
) >
) > James Kuyper (kuyper@wizard.net) wrote:
) > ) Matthias Meixner wrote:
) > ) >
) > [...]
) > ) >
) > ) > That's not really the case. In form of user defined conversions you
) > ) > already have overloading by return value and you can use this
) > ) > to implement overloading by return value (simply write a wrapper,
) > ) > that collects the function parameters and pack that into an
) > ) > object. Move the real functionality to the conversion function.)
) > )
) > ) Every time you add a conversion constructor or a type conversion
) > ) operator to a system, you increase the likelihood of unexpected or
) > ) ambiguous conversions.
) >
) > That's not really true for this case, since you add one additional class
) > and only conversion functions from this newly added class to existing
) > classes. So using this technique you cannot add additional ambiguities.
)
) What is the "this case" that you're referring to? You brought in user

'This case' is implementing overloading by return type using conversion
funcions as written above. E.g.:


class Foobar {

   float ff;

public:
   struct Overload {
      int param1,param2;
      Foobar *_this;

      Overload(int p1,int p2, Foobar *t) {param1=p1;param2=p2;_this=t;}

      operator float() { return _this->ff*param1*param2; }
      operator short() { return short((param1-param2)/_this->ff); }
   };

   friend class Foobar::Overload;

   Foobar(float x=0) {ff=x;}

   Overload f(int p1, int p2) { return Overload(p1,p2,this); }
};

There are also some minor drawbacks compared to real overloading by return
type:
- you cannot overload void
- if you do not use the return value, the function does not get executed!
- no additional implicit user defined conversion can be used.

) defined type conversion operators in general, as an example of how C++
) compilers can already handle overloading by return type in a special
) case.
) I was responding to that comment. I said nothing about adding a new
) class, only about adding "a conversion constructor or type conversion
) operator to a system". I didn't specify the system at all. I weakened my
) statement by calling it only a "likelihood", to cover the possibility
) that the system is so simple that no problem results. However, real
) systems often have a great many classes, with conversion constructors
) and type conversion operators connecting them to other classes, or even
) to non-class types. The new conversion constructor or type conversion
) operator I'm talking about would have a chance of being ambiguous with
) some of the other conversion paths that already exist.

As you can see the conversion functions only convert from the newly inserted
class "Foobar::Overload", so the rest of the code is not affected by the new
conversion functions. And therefore there are no new ambiguities compared
to real overloading by return type.

- Matthias Meixner

--
Matthias Meixner                   meixner@rbg.informatik.tu-darmstadt.de
Technische Universit   t Darmstadt
Rechnerbetriebsgruppe                          Telefon (+49) 6151 16 6670
Wilhelminenstra   e 7, D-64283 Darmstadt, Germany    Fax (+49) 6151 16 4701











---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Bruno Gustavs" <GustavsB@ch.sibt.com>
Date: 2000/06/07
Raw View
Why does c++ not support overloading by return value?
i.e. something like

class A
{
public:
  float  f();
  double f();
};

Regards
Bruno Gustavs



---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: comeau@panix.com (Greg Comeau)
Date: 2000/06/07
Raw View
In article <8hif95$bdj$1@pollux.ip-plus.net>,
Bruno Gustavs <GustavsB@ch.sibt.com> wrote:
>Why does c++ not support overloading by return value?
>i.e. something like
>
>class A
>{
>public:
>  float  f();
>  double f();
>};

Permit me to respond with some counter-questions:
* What becomes easier if it's allowed?
* What techniques in real code would be enhanced by such a capability?
* What about new problems it creates?

- Greg
--
Comeau Computing, Producers of Comeau C/C++ 4.2.42 (4.2.43 BETA starting)
Try Comeau C++ online at http://www.comeaucomputing.com/tryitout
Email: comeau@comeaucomputing.com / WEB: http://www.comeaucomputing.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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Steve Clamage <stephen.clamage@sun.com>
Date: 2000/06/07
Raw View
Bruno Gustavs wrote:
>
> Why does c++ not support overloading by return value?
> i.e. something like
>
> class A
> {
> public:
>   float  f();
>   double f();
> };


It's explained in the ARM and in D&E. It adds too much complexity
to the language for too little benefit.

It also increases the opportunity for introducing ambiguity, and
decreases the likelihood that you as a programmer will be able to
figure out which overloaded function will actually be called.

--
Steve Clamage, stephen.clamage@sun.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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: meixner@rbg.informatik.tu-darmstadt.de (Matthias Meixner)
Date: 2000/06/07
Raw View
Bruno Gustavs (GustavsB@ch.sibt.com) wrote:
) Why does c++ not support overloading by return value?
) i.e. something like
)
) class A
) {
) public:
)   float  f();
)   double f();
) };
)
) Regards
) Bruno Gustavs
)

It is actually possible to overload by return type using conversion functions,

[however the standard is somewhat broken in this area concerning conversions
 yielding reference types (see the thread 'which compiler is right' for a long
 discussion for finding out what is wrong ... ).]

Example (not tested):

class Overload {
   class A *t;
   Overload(class A *tt) :t(tt) {}

   operator float() { return t->f_float(); }
   operator double() { return t->f_double(); }
};

class A
{
   public:
      Overload f() { return Overload(this); }

      float f_float();
      double f_double();
}

- Matthias Meixner

--
Matthias Meixner                   meixner@rbg.informatik.tu-darmstadt.de
Technische Universit   t Darmstadt
Rechnerbetriebsgruppe                          Telefon (+49) 6151 16 6670
Wilhelminenstra   e 7, D-64283 Darmstadt, Germany    Fax (+49) 6151 16 4701


---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Bruno Gustavs" <GustavsB@ch.sibt.com>
Date: 2000/06/08
Raw View
"Greg Comeau" <comeau@panix.com> wrote in message
news:8hje6r$os$1@panix3.panix.com...
> Permit me to respond with some counter-questions:
> * What becomes easier if it's allowed?
Probably nothing with methods, but perhaps with functions. In my opinion
the advantage of overloading is, that you can save names. Example:
int powII(int, int); float powFI(float, int); float powFF(float, float);
can be replaced by a single (overloaded) name pow.
In this case it's nice to have overloading, likewise it would be
nice to have overloading by return values.

> * What techniques in real code would be enhanced by such a capability?
Probably none. Perhaps some strange techniques with overloading
unary operators like operator*() and operator->().

> * What about new problems it creates?
As C supports cyclic conversations between basic data types,
it would be impossible to decide in every case, which method to call.

Please accept that I just asked out of curiosity. Since Ada supports
this feature, there must by a reason why C++ does not.

Regards
Bruno Gustavs






---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 2000/06/08
Raw View
In article <8hlkp4$fu9$1@pollux.ip-plus.net>, Bruno Gustavs
<GustavsB@ch.sibt.com> writes
>Example:
>int powII(int, int); float powFI(float, int); float powFF(float, float);
>can be replaced by a single (overloaded) name pow.

What point are you making?  As the three differ in their parameter
types, where is the problem with overloading them?


Francis Glassborow      Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Stephen Cleary <scleary@jerviswebb.com>
Date: 2000/06/08
Raw View
"Bruno Gustavs" <GustavsB@ch.sibt.com> wrote:
> In my opinion
> the advantage of overloading is, that you can save names. Example:
> int powII(int, int); float powFI(float, int); float powFF(float,
float);
> can be replaced by a single (overloaded) name pow.
> In this case it's nice to have overloading, likewise it would be
> nice to have overloading by return values.
>
> ...
>
> > * What about new problems it creates?
> As C supports cyclic conversations between basic data types,
> it would be impossible to decide in every case, which method to call.
>
> Please accept that I just asked out of curiosity. Since Ada supports
> this feature, there must by a reason why C++ does not.

Implementation difficulty.  From "The C++ Programming Language", 3rd
ed., by Stroustrup, [7.4.1]: "Return types are not considered in
overload resolution.  The reason is to keep resolution for an
individual operator or function call context-independent."

That is, it makes implementing a compiler easier.  Return value
overloading is technically possible, but would make the overload
resolution much more complicated, possibly having to work on the entire
full-expression in order to get enough context.  Consider:
  int g();
  float g();
  int f(int x);
  int f(bool x);
  float f(float x);

  int tmp = f(g());

The call to g() is not resolved until the call to f() is resolved.  But
if parameters also participate in function overloading, then f() has to
have "tentative resolutions" based on its return type, then choose
"solid resolutions" based on its parameters.  Then do this at each
level in a full-expression.  In essence, it just gets too complicated.

Without return value overloading, we can just look at a single function
call "f(x)" and *know* what function it calls, no matter what context
it is in.

        -Steve


Sent via Deja.com http://www.deja.com/
Before you buy.

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Martin von Loewis <loewis@informatik.hu-berlin.de>
Date: 2000/06/08
Raw View
"Bruno Gustavs" <GustavsB@ch.sibt.com> writes:

> Probably nothing with methods, but perhaps with functions. In my opinion
> the advantage of overloading is, that you can save names. Example:
> int powII(int, int); float powFI(float, int); float powFF(float, float);
> can be replaced by a single (overloaded) name pow.

They can already in standard C++.

> Please accept that I just asked out of curiosity.

Accepted. However, it seems that the original response tried to make
you think about your own answer to the question, instead of having
other people answer it.

In another language I'm familiar with (SDL), you need that capability
to distinguish literals of different type. In C++ style, given

  int x = 1 + 2;
  double y = 3 + 4;
  duration d = 0;
  d = d + 1;

In SDL, there is no automatic conversion from int to double, so the
second line would be ill-formed (likewise, there is no conversion from
int to duration). To allow these statements, "1" could be int, double,
or duration - depending on context.

Now, in the second line, the context of the "3" is a plus. There are
several plus operations (duration+duration, time+duration, int+int,
etc), so it is hard to tell which one to use. In the end, the
assignment to the variable decides.

In the second line, the result is double, so the plus operator must
return double. Therefore, it must be

  "+" : double,double -> double;

Therefore, "3" and "4" must also be double. The entire procedure is
called "resolution by context".

In C++, this is not necessary: Looking at a literal, you always know
what type it has (1, 1.0, 1.0f, etc). Therefore, you know the argument
types in a function or operator call, which gives you the result type.
So the problem "what means 1+1" was solved differently in SDL and C++:
In C++, it is "integer", in SDL, it is "depends on the context". Both
solutions work in practice, C++ choses the one that logically follows
from the C background.

Hope this helps,
Martin

---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Bruno Gustavs" <GustavsB@ch.sibt.com>
Date: 2000/06/09
Raw View
"Francis Glassborow" <francis@robinton.demon.co.uk> wrote in message
news:r5RPSnA+7qP5Ewi3@robinton.demon.co.uk...
> >Example:
> >int powII(int, int); float powFI(float, int); float powFF(float, float);
> >can be replaced by a single (overloaded) name pow.
>
> What point are you making?  As the three differ in their parameter
> types, where is the problem with overloading them?

Sorry, but I feel missunderstood. The thing, I want to point out is, that
overloading by parameters is a well known technique in C++ and
allows you to save names. Similarly, overloading by return
values could save names. Saving name has nothing to do with
deep concepts, its just nice. Overloading in conjunction with
polymorhism in contrast has a deep impact on concepts.

Regards
Bruno Gustavs



---
[ 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://reality.sgi.com/austern_mti/std-c++/faq.html              ]