In the following code, I want it to use the std::vector
version of f()
if I call it with a std::vector
argument, but it's using the first one and complaining that std::to_string(const std::vector<T>&)
doesn't exist. My understanding of template overload resolution is that it should use the "more specialized" version. Somehow I think that doesn't apply here, because this is a function overload rather than a template overload. But it's not even using the normal function overload resultion rules, or else it would complain about an ambiguous call to f()
.
#include <vector>
#include <string>
template<typename T>
std::string f(T&& member) {
return std::to_string(member);
}
template<typename T>
std::string f(const std::vector<T>& member) {
return std::to_string(member[0]);
}
int main() {
int a = 42;
printf("%s\n", f(a).c_str()); // OK
std::vector<int> b = { 42 };
printf("%s\n", f(b).c_str()); // ERROR: to_string doesn't have a std::vector overload
return 0;
}
What am I doing wrong?
The type deduced by the forwarding reference is std::vector<int>&
, as opposed to the const std::vector<int>&
of the other overload. So when comparing the overloads, your non-const argument is a better match for the non-const qualified reference parameter, and so that one is chosen.
One way to address it is to account for both const qualifications with the help of another overload.
template<typename T>
std::string f(std::vector<T>& member) {
return f(std::as_const(member));
}
Here we obtain a const reference to member
with the help of std::as_const
and delegate to your original overload. You may want to provide an rvalue specific overload too, since the forwarding reference will deduce a better match for those as well when compared to your vector
overloads.
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