I cannot compile the following code.
void print_number(long n) {
std::cout << n << std::endl;
}
void print_number(float n) {
std::cout << n << std::endl;
}
void print_pair(std::pair<std::string, long> p) {
std::cout << std::get<1>(p) << std::endl;
}
void print_pair(std::pair<std::string, float> p) {
std::cout << std::get<1>(p) << std::endl;
}
int main() {
print_number(12l);
print_number(3.4f);
print_pair({"long", 12l});
print_pair({"float", 3.4f});
return 0;
}
print_number functions work well. However, compiler complains about the overloaded print_pair functions:
error: call of overloaded ‘print_pair(<brace-enclosed initializer list>)’ is ambiguous.
Are suffices in <brace-enclosed initializer list> or std::pair not working? How can I overload functions receiving a std::pair parameter?
Tl;dr
In order to solve the ambiguity, you can provide the correct type to the compiler:
print_pair(std::make_pair<std::string, long>("long", 12l));
print_pair(std::make_pair<std::string, float>("float", 3.4f));
or
print_pair(std::make_pair(std::string("long"), 12l));
print_pair(std::make_pair(std::string("float"), 3.4f));
The ambiguity problem arises from the fact "long" and "float" are not std::string, but rather const char[].
So when you try to construct a std::pair using the following expression: std::pair{"long", 12l}, what you obtain is a std::pair<const char[5], long>.
(The same for the float; i.e., std::pair<const char[5], float>).
Your overload print_pair accepts std::pair<std::string, long> or std::pair<std::string, float>. None of the previous types match, so the compiler has to perform a conversion. Because of that, it cannot automatically deduct what conversion you want to perform. Both are valid.
For example:
std::pair<const char[5], long>
|
----------------------------------------------------------------
v v
std::pair<std::string, long> std::pair<std::string, float>
To "prove" the problem is the std::string (neither long or float), you can also solve the ambiguity constructing a proper std::string (instead of an array of char):
print_pair(std::make_pair(std::string("long"), 12l));
print_pair(std::make_pair(std::string("float"), 3.4f));
Starting from C++17, this boilerplate can be simplified with:
using namespace std::string_literals;
print_pair(std::pair{"long"s, 12l});
print_pair(std::pair{"float"s, 3.4f});
With print_pair({"long", 12l});, there are 2 possible overloads:
void print_pair(std::pair<std::string, long>)void print_pair(std::pair<std::string, float>){"long", 12l} has no types, but is valid initialization for both std::pair<std::string, long> and std::pair<std::string, long>.
So the call is ambiguous.
print_pair(std::pair{"long", 12l}); would also be ambiguous
as std::pair<const char*, long> can equally be converted to std::pair<std::string, long> and std::pair<std::string, long>.
You have to call it:
print_pair(std::pair{std::string("long"), 12l}); to have exact match.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With