为什么重载分辨率不选择模板函数的 std::vector 重载?



在下面的代码中,如果我使用 std::vector 参数调用它,我希望它使用 std::vector 版本的 f(),但它使用的是第一个并抱怨std::to_string(const std::vector<T>&)不存在。我对模板重载分辨率的理解是它应该使用"更专业"的版本。不知何故,我认为这在这里不适用,因为这是函数重载而不是模板重载。但它甚至没有使用正常的函数重载结果规则,否则它会抱怨对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("%sn", f(a).c_str()); // OK
    std::vector<int> b = { 42 };
    printf("%sn", f(b).c_str()); // ERROR: to_string doesn't have a std::vector overload
    return 0;
}

我做错了什么?

转发引用推导出的类型是std::vector<int>&,而不是其他重载的const std::vector<int>&。因此,在比较重载时,您的非常量参数与非常量限定的引用参数更匹配,因此选择一个。

解决这个问题的一种方法是在另一个重载的帮助下考虑两个常量限定。

template<typename T>
std::string f(std::vector<T>& member) {
    return f(std::as_const(member));
}

在这里,我们在 std::as_const 的帮助下获得对 member 的常量引用,并委托给您的原始重载。您可能还希望提供特定于右值的重载,因为与vector重载相比,转发引用也将推断出更好的匹配。

最新更新