views:

415

answers:

4

C++ does not allow polymorphism for methods based on their return type. However, when overloading an operator this seems possible.

Does anyone know why? I thought operators are handled like methods internally.

Edit: Here's an example:

struct func {
    operator string() { return "1";}
    operator int() { return 2; }
};

int main( ) {
    int x    = func(); // calls int version
    string y = func(); // calls string version
    double d = func(); // calls int version
    cout << func() << endl; // calls int version
}
+3  A: 

That's not return type. That's type conversion.

Consider: func() creates an object of type func. There is no ambiguity as to what method (constructor) will be invoked.

The only question which remains is if it is possible to cast it to the desired types. You provided the compiler with appropriate conversion, so it is happy.

EFraim
+10  A: 

Conversion operators are not really considered different overloads and they are not called based on their return type. The compiler will only use them when it has to (when the type is incompatible and should be converted) or when explicitly asked to use one of them with a cast operator.

Semantically, what your code is doing is to declare several different type conversion operators and not overloads of a single operator.

Mehrdad Afshari
A: 

Overload resolution chooses between multiple candidate functions. In this process, the return type of candidates is indeed not considered. However, in the case of conversion operators the "return type" is critically important in determining whether that operator is a candidate at all.

MSalters
+1  A: 

There isn't really a technical reason to prevent overloading of functions on the result types. This is done in some languages like Ada for instance, but in the context of C++ which has also implicit conversions (and two kind of them), the utility is reduced, and the interactions of both features would quickly leads to ambiguities.

Note that you can use the fact that implicit conversions are user definable to simulate overloading on result type:

class CallFProxy;
CallFProxy f(int);

class CallFProxy {
   int myParameter;
   CallFProxy(int i) : myParameter(i) {}
public:
   operator double() { std::cout << "Calling f(int)->double\n"; return myParameter; }
   operator string() { std::cout << "Calling f(int)->string\n"; return "dummy"; }
};
AProgrammer