编译器错误"没有用于呼叫"的匹配功能在我的例子中,链接列表中的查找功能。
为什么会出现此错误?
功能
template<class T>
int find(std::shared_ptr<Node<T>> ptr, T val) {
int pos(0);
while (ptr) {
if (ptr->val == val)
return pos;
else {
ptr = ptr->next;
pos++;
}
}
return -1; // Not found
}
调用
std::cout << "Pos: " << find(myFloat, 9.83) << std::endl;
myFloat
是shared_ptr
,是浮点列表的根节点,已成功填充如下:
浮动的链接列表
2.5 ⟹ 3.7 ⟹ 4.8 ⟹ 7.93 ⟹ 0.96 ⟹ 9.83 ⟹ 7.45
STRUCT
template<class T>
struct Node {
Node(T k):val(k){}
T val;
std::shared_ptr<Node<T>> next = nullptr;
};
错误
没有匹配功能可以调用&#39;查找&#39;
myFloat定义
std::shared_ptr<Node<float>> myFloat = { std::make_shared<Node<float>>(0.) };
答案 0 :(得分:3)
由于您没有向find
提供任何显式模板参数(如find<float>(myFloat, 9.83)
中所述),编译器必须从函数参数中推导出模板参数T
。
在模板参数推导期间,函数参数类型中模板参数的每次出现都在推导上下文或非推导上下文中。在您的情况下,两者都被视为推断上下文。为推导的上下文中的模板参数的每个外观确定类型或值。
myFloat
的类型为std::shared_ptr<Node<float>>
,第一个函数参数的类型为std::shared_ptr<Node<T>>
,因此T
推导为float
。
9.83
的类型为double
,第二个函数参数的类型为T
,因此T
推断为双倍。
由于模板参数T
被推断为两种不同的类型,因此总体扣除失败!当多次推导出相同的模板参数时,所有结果必须相同。
那么你能做些什么才能让它成功呢?
令人不快的解决方案是单独留下模板并要求呼叫者小心使用它。 find<float>(myFloat, 9.83)
可以通过显式提供模板参数来工作。 find(myFloat, 9.83f)
可以通过更改第二个函数参数的类型来工作。但最好让模板更灵活,更友好。
一个简单的解决方法是只使用两个不同的模板参数。
template<class T, class U>
int find(std::shared_ptr<Node<T>> ptr, U val);
然后该函数只需要==
运算符适用于T
和U
类型。
或者如果您希望将第二个函数参数隐式转换为Node
中使用的类型,您可以有意将第二次使用T
转换为非推导的上下文:
template <typename T>
struct identity {
using type = T;
};
template<class T>
int find(std::shared_ptr<Node<T>> ptr,
typename identity<T>::type val);
通过显示::
的左侧,第二个T
现在是非推断的上下文,因此表达式find(myFloat, 9.83)
将仅从第一个参数中推导出T
,从而得到在T=float
中,然后替换为模板函数声明。 typename identity<float>::type
向float
发送,因此会有double
文字9.83
隐式转换为float
以调用该函数。