Overload a C++ Function According to the Return Value

Overload a C++ function according to the return value

class mul
{
public:
mul(int p1, int p2)
{
param1 = p1;
param2 = p2;
}
operator int ()
{
return param1 * param2;
}

operator std::string ()
{
return std::string(param2, param1 + '0');
}

private:
int param1;
int param2;
};

Not that I would use that.

Overloading by return type

No there isn't. You can't overload methods based on return type.

Overload resolution takes into account the function signature. A function signature is made up of:

  • function name
  • cv-qualifiers
  • parameter types

And here's the quote:

1.3.11 signature

the information about a function that participates in overload
resolution (13.3): its parameter-type-list (8.3.5) and, if the
function is a class member, the cv-qualifiers (if any) on the function
itself and the class in which the member function is declared. [...]

Options:

1) change the method name:

class My {
public:
int getInt(int);
char getChar(int);
};

2) out parameter:

class My {
public:
void get(int, int&);
void get(int, char&);
}

3) templates... overkill in this case.

How to achieve function overloading in C?

There are few possibilities:

  1. printf style functions (type as an argument)
  2. opengl style functions (type in function name)
  3. c subset of c++ (if You can use a c++ compiler)

Function return type overloading C++

You cannot overload based on return type alone. In a nutshell, the compiler figures out what overload to call based on the arguments. Hence, you cannot distinguish two overloads based only on return type:

int f() { return 42; }
double f() { return 3.14; } // error redeclaration of f()

f(); // calls what function ?!?

When parameter types differ, two overloads can have different return types:

 int g() { return 42; }          // (1)
double g(int) { return 3.14; } // (2)

g(); // calls (1)
g(1); // calls (2)

While vanilla overloading does not let you overload based only on the return type, there is a neat trick that can emulate it. Bear with me.

The above f overloads cause a compiler error, because they arent a valid overload set (differ only by return type). But we can define two seperate functions:

int f_int(){ return 42; }    
double f_double() { return 3.14; }

We can define a type whose purpose is nothing but to be convertible to either an int or a double. During that conversion we can call the respective f_x:

struct foo {
operator int() { return f_int(); }
operator double() { return f_double(); }
};

Now these two lines:

int x = foo{};
double y = foo{};

call f_int or f_double, respectively, based on what we assign it too.

live demo

However, take this with a grain of salt. It is rare that you actually need to overload based on return type only. Those two lines can be rather obscure when it isnt clear from context what is happening. Implicit conversions are always a source of confusion. Last but least, it also doesn't go well with "almost always auto".

C++ overload function by return type

You're not overloading on return type, you're specializing a function template and when the Foo<B>(int) specialization forms the invalid type B::_foo that specialization is removed from the overload set by SFINAE, leaving the Foo<B>(char) function as the only viable function.

In more detail, the call to Foo<A>(0) first performs name lookup to find all the Foo names in scope, then instantiates any function templates to find the overload candidates, then overload resolution chooses the best match.

The step of instantiating the function templates produces these two function declarations:

int Foo<A>(int);
A Foo<A>(char);

Overload resolution chooses the first one as the best match.

However when calling Foo<B>(0) the instantiations produce these declarations:

<invalid type>  Foo<B>(int);
B Foo<B>(char);

The first declaration is not valid, so there is only one candidate for overload resolution, so that is the one that gets called.

In your Bar example the invalid type that gets formed during instantiation is not in "the immediate context" of the function declaration (it's in the function definition i.e. body) so SFINAE does not apply.

function overloading can only be done by return value and const in C++?

You can't overload on return type, for obvious reasons.

You can however overload on the constness of the implicit instance argument. Compare:

aa.f1(b);
static_cast<A const &>(aa).f1(b);

(This example also illustrates why it makes no sense to attempt to "overload on return type": How would you make the decision in this example?)

return value of operator overloading in C++

Some operators return by value, some by reference. In general, an operator whose result is a new value (such as +, -, etc) must return the new value by value, and an operator whose result is an existing value, but modified (such as <<, >>, +=, -=, etc), should return a reference to the modified value.

For example, cout is a std::ostream, and inserting data into the stream is a modifying operation, so to implement the << operator to insert into an ostream, the operator is defined like this:

std::ostream& operator<< (std::ostream& lhs, const MyType& rhs)
{
// Do whatever to put the contents of the rhs object into the lhs stream
return lhs;
}

This way, when you have a compound statement like cout << x << y, the sub-expression cout << x is evaluated first, and then the expression [result of cout << x ] << y is evaluated. Since the operator << on x returns a reference to cout, the expression [result of cout << x ] << y is equivalent to cout << y, as expected.

Conversely, for "string + string", the result is a new string (both original strings are unchanged), so it must return by value (otherwise you would be returning a reference to a temporary, which is undefined behavior).

Function overloading with different return types

How will I make the convert() work if I want it to have it different return types by overloading the function ?

You can create a simple function template.

template <typename T>
T convert(std::string const& num){
std::istringstream ss(num);
T d_num;
ss>>d_num;
return d_num;
}

and specialize it for std::string so that the input argument is used to copy construct the returned std::string.

template <>
std::string convert<std::string>(std::string const& in){
return in;
}

and use it as:

auto d1 = convert<double>(st);
auto i1 = convert<int>(st);

Why can't functions be overloaded by return type?

You can't overload on return types as it is not mandatory to use the return value of the functions in a function call expression.

For example, I can just say

GetVal();

What does the compiler do now?



Related Topics



Leave a reply



Submit