It's because of how the function tables and overloaded functions work in C++.
When the compiler reads your std::string some_function();
it creates a spot for it to reference in the binary and says if "this function is ever called jump to this spot".
So we have a vtable that looks like this...
(Address offset) (Symbol)
0x???????? std::string somefunction();
Now it gets to your auto some_function() {...}
. Normally it would first look in the function table to see if auto somefunction();
exists in the table or some variation there of, but the compiler notices that this is a implementation and it has the auto keyword so to reduce the entropy it writes *blank* some_function();
to the function table and ties to solve the return type.
Now the Function table looks like this...
(Address offset) (Symbol)
0x???????? std::string somefunction();
0x???????? ????? somefunction();
So it chugs along compiling code into binary when it finds out the return type which in this case is std::string
. The compiler now knows what the return type is so it goes to the function table and changes auto somefunction();
too std::string somefunction();
.
Now the Function table looks like this...
(Address offset) (Symbol)
0x???????? std::string somefunction();
0x???????? std::string somefunction();
Now the compiler goes back and continues to compile the function. Once it's done it goes back and finishes up the vtable only to find the same symbol is in there twice. It's now ambiguous to which symbol we are referring too.
So what is the reason for this?
Not 100% sure but vtables are made long before your code is worked down enough to allow for the deduction type to be made. So the only option the compiler has to work with at that stage in time is to just assume it's a new symbol. It's just something I've noticed looking at symbol tables all day and writing my own C++11 compiler.
I however can in no way speak for other compilers where lots of optimizations and other steps are introduced, I just work with the bare bones, however that is my understanding of the standard.
One last thing the type is completely arbitrary. It doesn't even matter if they don't match at the time of deduction. It never get's that far. The problem arises that there are two of the same symbols in the table, and you can't overload on return types.