C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Idiom for overloading on return type

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Maciej Sobczak
Guest





PostPosted: Wed Oct 27, 2004 2:00 pm    Post subject: Idiom for overloading on return type Reply with quote



Hi,

Consider this code:

#include <iostream>

using namespace std;

void do_int(int &i)
{
cout << "computing int resultn";
i = 7;
}

void do_double(double &d)
{
cout << "computing double resultn";
d = 3.1415926;
}

struct ReturnDispatch
{
operator int() const
{
int res;
do_int(res);
return res;
}

operator double() const
{
double res;
do_double(res);
return res;
}
};

ReturnDispatch foo()
{
return ReturnDispatch();
}

int main()
{
int i = foo(); // (1)
cout << i << 'n';

double d = foo(); // (2)
cout << d << 'n';
}

An interesting feature is that when the return value from foo() is
ignored, it is not computed at all. For some it may be a bug, but then
it is possible to instrument the destructor of ReturnDispatch to do
something relevant in the given context.

I would like to know whether this idiom is in use and what is your
experience with it.

--
Maciej Sobczak : http://www.msobczak.com/
Programming : http://www.msobczak.com/prog/


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Chris Theis
Guest





PostPosted: Fri Oct 29, 2004 1:48 am    Post subject: Re: Idiom for overloading on return type Reply with quote




"Maciej Sobczak" <no_spam (AT) no_spam (DOT) com> wrote

Quote:
Hi,

Consider this code:

#include
using namespace std;

void do_int(int &i)
{
cout << "computing int resultn";
i = 7;
}

void do_double(double &d)
{
cout << "computing double resultn";
d = 3.1415926;
}

struct ReturnDispatch
{
operator int() const
{
int res;
do_int(res);
return res;
}

operator double() const
{
double res;
do_double(res);
return res;
}
};

ReturnDispatch foo()
{
return ReturnDispatch();
}

int main()
{
int i = foo(); // (1)
cout << i << 'n';

double d = foo(); // (2)
cout << d << 'n';
}

An interesting feature is that when the return value from foo() is
ignored, it is not computed at all. For some it may be a bug, but then
it is possible to instrument the destructor of ReturnDispatch to do
something relevant in the given context.

To be exact this is not really overloading on return type but youŽre
instrumenting the conversion operators. What you do is to supply two
different conversion operators and which the compiler tries to use. For
example:

int i = foo();

The most naturaly thing for the compiler would be to expect an integer as
the rvalue. However, there is none because the return value of foor() is
ReturnDispatch. The next best thing the compiler tries is, whether it can
convert ReturnDispatch to an integer, which works because you have supplied
the user defined conversion function and voila - youŽre done. If you do not
assign the return value there is simply no need for the conversion.
But there are some caveats which are discussed in more details in More
Effective C++ by Scott Meyers (could also be the first book Effective C++
but IŽm not sure as I donŽt know it by heart).

Quote:

I would like to know whether this idiom is in use and what is your
experience with it.


This technique is used in the streams of the standard library. You have
surely encountered something like this:

ifstream Input("foo.txt");
if( !Input) { // <==
cout << "ouch" << endl;
}

The interesting part is the if() statement because it expects a condition
which evaluates to true or falls. The reason why this works is because the
stream classes supply a conversion for void* which returns the status of the
fail() function. You could now ask why operator bool() is not overloaded
instead. Consider the following (of course wrong) code:

cin << x; // << is a typo!

This would result in the conversion of cin to bool, followed by a conversion
to int which is shifted by x bits. Consequently youŽll get a syntactically
correct program which certainly does not what you want!

HTH
Chris



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Maciej Sobczak
Guest





PostPosted: Fri Oct 29, 2004 2:32 pm    Post subject: Re: Idiom for overloading on return type Reply with quote



What you got previously is unnecessarily complex.
The whole idiom may be shorter:

int do_int()
{
cout << "computing int resultn";
return 7;
}

double do_double()
{
cout << "computing double resultn";
return 3.14159265;
}

struct ReturnDispatch
{
operator int() const { return do_int(); }
operator double() const { return do_double(); }
};

ReturnDispatch foo() { return ReturnDispatch(); }

int main()
{
int i = foo();
cout << i << 'n';

double d = foo();
cout << d << 'n';
}

or even with templates:

#include
using namespace std;

template <typename T> T compute();

template <>
int compute()
{
cout << "computing int resultn";
return 7;
}

template <>
double compute()
{
cout << "computing double resultn";
return 3.14159265;
}

struct ReturnDispatch
{
template operator T() const { return compute<T>(); }
};

ReturnDispatch foo() { return ReturnDispatch(); }

int main()
{
int i = foo();
cout << i << 'n';

double d = foo();
cout << d << 'n';
}

Anyway - my question is still valid:

Quote:
I would like to know whether this idiom is in use and what is your
experience with it.

--
Maciej Sobczak : http://www.msobczak.com/
Programming : http://www.msobczak.com/prog/


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Craig Henderson
Guest





PostPosted: Fri Oct 29, 2004 2:38 pm    Post subject: Re: Idiom for overloading on return type Reply with quote

Maciej Sobczak <no_spam (AT) no_spam (DOT) com> wrote


Quote:

ReturnDispatch foo()
{
return ReturnDispatch();
}

int main()
{
int i = foo(); // (1)
cout << i << 'n';

double d = foo(); // (2)
cout << d << 'n';
}

An interesting feature is that when the return value from foo() is
ignored, it is not computed at all. For some it may be a bug, but then
it is possible to instrument the destructor of ReturnDispatch to do
something relevant in the given context.

I would like to know whether this idiom is in use and what is your
experience with it.

What would cout << foo(); produce?

An alternative might be

template T foo(T=T())
{
return ReturnDispatch();
}

The default parameter enables overloading without an explicit parameter, but
calling is different:
cout << foo cout << foo
or even
double d;
cout << foo(d);

or is that getting convoluted?

-- Craig

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.