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;
}