2

Is there any particular reason why C++ disallows overloading based on the presence or absence of a return-value? Like this:

void f(); //(1)
int f(); //(2)
int main(){
 f(); // calls (1)
 int x = f(); // calls (2)
 return x;
}

The void-variant is called whenever the return-value is ignored, so there shouldn't be any problem with overload-resolution. Could be useful even in the standard library, for things like vector::pop_back(). So why is this not allowed?

Edit: It has been noted that the non-void function can be called in a void context as well. I'm aware of this. I just want the compiler to prefer the void function if there is one.

asked Mar 17, 2014 at 4:19
3
  • Because you can also call the second one by f(); (not catching its return value). Commented Mar 17, 2014 at 4:23
  • 1
    My guess would be readability, especially when dealing with simultaneous implicit casts. It sounds like it would also force people to use the return value, because for int g and double g, calling (void)g() would be impossible for the compiler to decide what to do. Keep in mind overloads are never "necessary", they only improve readability and make it easier to remember what function to use, and if it's not going to succeed at making it more readable, then it won't be worth it for them to add. Commented Mar 17, 2014 at 4:24
  • @VoidStar I do not want to overload based on different result types, just based on the presence or absence of a result type. And sometimes overloads are necessary, without e.g. overloads for sin you had a hard time using that function from within templates. Commented Mar 17, 2014 at 4:36

5 Answers 5

3

This is a language rule, in The C++ Programmin Language 4th edition, you can read:

Return types are not considered in overload resolution. The reason is to keep resolution for an individual operator (§18.2.1, §18.2.5) or function call context-independent.

but looking at your example its preety clear which function should be called:

f(); // calls (1)
int x = f(); // calls (2)

in (1) a void version, while in (2) non void version. You can read in this answer Function overloading by return type? that there are languages that allow overloading on return types.

In c++ you can achive that with some tricks, like with conversion operators, the problem is with how to call function that return void type. Below is my approach to solve this (or rather abuse language rules). I dont like the fact that void version is called in destructor - I suppose it should not be allowed to throw then. Any way this is only for fun, I would never use such code. I have compiled and run it with success on VS2005,g++4.8,clang (from http://rextester.com/runcode - not sure which version). Also I though that return value optimization would remove all the destructor calls, but it looks like it actually is not doing this.

http://coliru.stacked-crooked.com/a/6e052cc7c1bb56ca

#include<iostream>
struct SomeClass {
 int nonVoidFunc() {
 std::cout << "nonVoidFunc()" << std::endl;
 return 0;
 }
 void voidFunc() {
 std::cout << "voidFunc()" << std::endl;
 }
};
class Proxy {
 SomeClass& sc;
 bool callVoid;
 Proxy(Proxy& p_sc) : sc(p_sc.sc), callVoid(false) { }
 Proxy& operator=(const Proxy& pr) { return *this;}
public:
 Proxy(SomeClass& p_sc) : sc(p_sc), callVoid(1) {}
 ~Proxy() {
 if ( callVoid) sc.voidFunc(); 
 }
 template<typename T> operator T() {
 callVoid = false;
 return sc.nonVoidFunc();
 }
public:
 Proxy func() { return *this; }
};
int main() {
 SomeClass sc;
 Proxy p1(sc);
 int n = p1.func(); // prints nonVoidFunc()
 (void)n; 
 p1.func(); // prints voidFunc()
 return 0;
}
answered Mar 17, 2014 at 10:05
Sign up to request clarification or add additional context in comments.

1 Comment

This is quite cool, thanks, but it doesn't help me understand why the rules are the way they are. By now I believe the only reason is that nobody cared, probably because they don't consider it sufficiently useful.
1

A function that retuns a non-void type can be called in a context where the return value is ignored. For instance, the C function printf() has a return value of type int, but it's rarely used in practice.

In other words, you can call the function int f() with:

f();

where the return value is ignored, only the side effect is used.

answered Mar 17, 2014 at 4:24

1 Comment

Sure, whenever there is no void overload for a function the non-void function is being called. But I want the compiler to prefer the void-function if there is one.
0

yes there is. In C++ or Java a method in any given class are recognized by the method signature, the signature here is defined as name of the method and type and number of parameters the method accepts. The return type is not part of the method signature and therefore having a method overloaded that differs only by their return type is not acceptable in these programming languages. In your example: int x = f(); you are assuming that the user will type int x however the programmer doesn't really have to do that! With the preamble I explained about method signature when the user calls f() there is no way for the compiler to recognize if you re calling the first one or the second one. That being said some modern programming languages allow overloading based on the return type. You can find a more thorough explanation here

answered Mar 17, 2014 at 4:34

Comments

0

Function declarations that differ only in the return type cannot be overloaded.

Your example with void f() and int f() is just a particular case of this rule.

In theory there's no reason I can think of for why the C++ standard couldn't make a special exception and allow overloading between void and non-void returning functions with the same parameter list with overload resolution along the same lines as what you proposed. However, it is unlikely that such an exception would be approved unless it were deemed reasonably useful...

(BTW, if you think this would be quite useful, and are prepared to defend that position, consider posting to the std-proposals mailing list.)

answered Mar 17, 2014 at 4:40

5 Comments

I'm pretty sure everybody sometimes hated the fact that vector::pop_back doesn't return a value, does this count as reasonably useful?
@pentadecagon one reason why vector::pop_back is designed not to return the popped value is that if an exception occurs during the assignment in x = v.pop_back() then the value disappears from v entirely. Allowing this overload wouldn't address that issue
@marcin_j aha, too fast for me
This is a red herring. In practice nobody cares because if an assignment operator throws you are in very deep trouble anyway, and a vanished object doesn't really matter anymore.
@pentadecagon well, if you're so sure, submit a proposal.
0

In C++, the return type of functions is not a part of the mangled name which is generated by the compiler for uniquely identifying each function. The

  • No. of arguments
  • Type of arguments
  • Sequence of arguments

are the parameters which are used to generate the unique mangled name for each function. It is on the basis of these unique mangled names that compiler can understand which function to call even if the names are same (overloading).


Edit: It would be possible once name mangling have included the return type by the standard and at the same time not allowing to call a function without ignoring its return type.

answered Mar 17, 2014 at 4:37

2 Comments

Name-mangling isn't standardized, compilers can do what they want, and I believe Visual Studio does it differently. Anyway, compilers could do it differently if overloading based on the presence of a return type were allowed.
@pentadecagon Yes, it will be possible if return type is included in the name-mangling.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.