views:

975

answers:

5

Why don't we see C-like languages that allow for callables with polymorphism in the return type? I could see how the additional type inference would be a hurdle, but we have plenty of languages with full-fledged type inference systems (that work for varying levels of "work").

Edit: By return type polymorphism I mean overloading the function signature only in the return type. For example, C++ and Java only allow overloading in the type of the formal parameters, not in the return type.

+4  A: 

If by "return type polymorphism" you mean overloading based on the return value type, I'm not sure about other languages, but for C++ here's the answer (pretty much from the horse's mouth):

Function return types don't come into play in overload resolution simply because Stroustrup (I assume with input from other C++ architects) wanted overload resolution to be 'context independent'. See 7.4.1 - "Overloading and Return Type" from the "C++ Programming Language, Third Edition".

The reason is to keep resolution for an individual operator or function call context-independent.

They wanted it to be based only on how the overload was called - not how the result was used (if it was used at all). Indeed, many functions are called without using the result or the result would be used as part of a larger expression. One factor that I'm sure came into play when they decided this was that if the return type was part of the resolution there would be many calls to overloaded functions that would need to be resolved with complex rules or would have to have the compiler throw an error that the call was ambiguous.

And, Lord knows, C++ overload resolution is complex enough as it stands...

Michael Burr
True, any function where you did this would have undefined behavior in a void context -- unless there were an overloaded void return type.
cdleary
A: 
double x = (double)foo();

The above is ambiguous if there are versions of foo() that can return double, int, float, etc.

Ryan Fox
yes but string s = foo(); double x = foo(); int i = foo(); are not ambiguous. Why would I cast the return type of foo to double if foo already returned a double? and if no version of foo returned a double then the (first) cast should match the overloaded return type...
Steven A. Lowe
A: 

Because of auto-conversion of types, it is not obvious to know which function to call when return types are close.

PhiLho
+2  A: 

i would love to see this feature in some language, not only so that function foo could return a double or an int or a string, but also so that foo could return a structure or objects of different classes. Disambiguating calls would be fairly trivial - if the call is ambiguous, require a cast to select the return type desired. Example:

string s = foo();    //foo returns a string
double x = foo();    //foo returns a double
int i = foo();       //foo returns an integer
float f = (float)(int)foo();    //call the int foo and convert to float

in addition

Animal a = fooFactory();    //fooFactory returns an Animal
Plant p = fooFactory();     //foofactory returns a Plant

these situations do not come up very often, but when they do the workaround is often fairly ugly...

Steven A. Lowe
A: 

In C++ you can do this with classes to a large extent. For example, say I have a data type that is routinely converted to ASCII on input and output;

typedef char* pchar;

class   MyType
{
public:

 operator pchar() { return(ConvertToASCII()); }
 MyType& operator=(char* input) { ConvertFromASCII(input); return(*this); }

 pchar ConvertToASCII();
 void ConvertFromASCII(pchar ASCII);
}

This type of thing is often used in C++ frameworks. For example, have a look at the implmentation of the MFC CString class. IMHO, it is a very useful tool, albeit dangerous in certain circumstances.

Shane MacLaughlin