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