I am learning new C++ semantics and I got an error with this program:
#include <iostream>
#include <string>
#include <utility>
std::string foo(std::string str)
{
return str + " call from normal";
}
std::string foo(const std::string& str)
{
return str + " call from normal";
}
std::string foo(std::string&& str)
{
return str + " call from ref ref";
}
int main()
{
std::string str = "Hello World!";
std::string res = foo(str);
std::string&& res_ref = foo(std::move(str));
std::cout << "Res ref = " << res_ref << std::endl;
std::cout << "Str = " << str << std::endl;
return 0;
}
The error is:
:23:30: error: call of overloaded ‘foo(std::__cxx11::string&)’ is ambiguous std::string res = foo(str);
Why is the call ambiguous?
When you have;
std::string res = foo(str);
There are two viable candidates:
foo(std::string ); // #1
foo(std::string const& ); // #2
There are many, many steps in determining which function to choose when given multiple candidates. But in this case, both choices are completely indistinguishable - there is simply no preference in the overload resolution between string
and string const&
for an argument. Similarly, there is no preference between string
and string&&
for an rvalue argument, so your second call is also considered ambiguous.
Generally, the rules for preferring one function to another have to do with which one is more specific. For instance, given a function taking string&
and one taking string const&
, the former can only be called with non-const lvalue references to string
, but the latter can be called with a whole bunch of stuff, so when both are viable, the former is preferred (specifically, due to [over.ics.rank]/3.2.6). But in this case, anything that you could call #1
with, you could call #2
with. And anything you could call #2
with, you could call #1
with. So there isn't any reason to prefer one to the other.
You should simply remove that overload, leaving your two:
foo(std::string const& ); // #2
foo(std::string&& ); // #3
For lvalue std::string
s, only #2 is viable. For rvalue std::string
s, both are viable, but #3 would be preferred (by the general guideline that it is more specific - and specifically due to [over.ics.rank]/3.2.3).