views:

176

answers:

8

I realize standard C++ only picks functions by argument type, not return type. I.e I can do something like:

void func(int);
void func(double);

but not

double func();
int func();

Where in the former, it's clear, in the latter, it's ambigious. Are there any extensions that lets me tell C++ to pick which function to use also by return type?

Thanks!

+5  A: 

If you had those two functions, which one should the compiler pick if you simply called:

func();

The closest you can get to what you are asking for would be to use a specialized function template (note that you want to be very careful when specializing function templates):

template <typename ReturnT>
ReturnT func();

template <>
double func<>() { return 42; }

template <>
int func<>() { return 0; }

Then you can call it as follows:

func<int>();
func<double>();
James McNellis
I do agree with you, but it should be possible to implement for the case where you call `int i = func();` and to only give an error when there isn't a `void` function and `func()` is called without an accompanying assignment. I wouldn't like that though.
Chinmay Kanchi
A: 

Because compiler don't know what function you calls!

Svisstack
A: 

No; it's actually pretty hard to implement too. I vaguely remember hearing that it was a P-NP problem.

John Weldon
A: 

None that I know of. You'd best name the functions differently or perhaps use a different argument to let the compiler (not you) distinguish them.

Alternatively, do:

struct myReturnType {
  int myInt;
  double myDouble;
};

myReturnType func() {
  ...
}
mingos
+4  A: 

Why not just name them differently? If they're returning different things, it sounds to me as though they're probably doing different things. Why obfuscate your code?

Jon Cage
+3  A: 

You cannot have two functions in the same scope that have the same name and signature (ie. argument types). Yet you can create a function that will behave differently depending on what variable you assign the result to, as in:

int x=f();
double x=f(); // different behaviour from above

by making f() return a proxy with an overloaded cast operator.

struct Proxy
{
  operator double() const { return 1.1; }
  operator int() const { return 2; }
};

Proxy f()
{
  return Proxy();
}

See http://ideone.com/ehUM1

Not that this particular use case (returning a different number) is useful, but there are uses for this idiom.

jpalecek
A: 

There's one context in C++ where the result of overload resolution depends on the "return type", left-hand side of the expression. It is intialization/assignment of the function pointer value with the adress of a function. It works with an explicit object of the left-hand size as well as with a temporary object created by an explicit type cast.

In your case it can be used to select one specific function from two overloaded ones. For example:

int (*pfunc)() = func; // selects `int func()`
int i = pfunc(); // calls `int func()`

You can use this technique to force overload resolution in one line, although it doesn't look too elegant

int i = ((int (*)()) func)(); // selects and calls `int func()`

Again, in this case you perform the overload resolution manually. C++ has no feature that would resulkt in implicit overload resolution based on the return type (aside from what I illustrated above).

AndreyT
A: 

It's a bit dangerous, but you can create a union of the different types that you want to return, and combine both of these into one function that returns a union. For example:

typedef union {
  double d;
  int    i;
} my_union;

my_union func();

However, this would require the function and the caller to somehow know what data type to expect as a result, and can lead to all sorts of errors. You can do this, but I definitely wouldn't recommend it.

bta