简体   繁体   English

在模板化链表中调用查找没有匹配函数

[英]No matching function for call to find in templated linked list

Complier error "No matching function for call to" in my case a find function in a linked list. 编译器错误“没有用于调用的匹配函数”在我的情况下是链接列表中的查找函数。

Why this error? 为什么这个错误?

Function 功能

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
}

Invocation 调用

std::cout << "Pos: " << find(myFloat, 9.83) << std::endl;

myFloat is a shared_ptr , and root node for a list of floats, successfully populated as follows: myFloat是一个shared_ptr ,以及一个浮点列表的根节点,已成功填充如下:

Linked List of Floats 浮动的链接列表

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;
};

Error 错误

No matching function for call to 'find' 调用'find'没有匹配功能

myFloat Definition myFloat定义

std::shared_ptr<Node<float>> myFloat = { std::make_shared<Node<float>>(0.) };

Since you didn't provide any explicit template arguments to find (as in find<float>(myFloat, 9.83) ), the compiler must deduce the template argument T from the function arguments. 既然你没有提供任何明确的模板参数,以find (如find<float>(myFloat, 9.83)编译器必须推导出模板参数T从函数的参数。

During template argument deduction, every appearance of a template parameter in the function parameter types is either in a deduced context or non-deduced context. 在模板参数推导期间,函数参数类型中模板参数的每次出现都在推导的上下文或非推导的上下文中。 In your case, both are considered deduced context. 在您的情况下,两者都被视为推断上下文。 A type or value is determined for each appearance of a template parameter in a deduced context. 为推导的上下文中的模板参数的每个外观确定类型或值。

myFloat has type std::shared_ptr<Node<float>> and the first function parameter has type std::shared_ptr<Node<T>> , so T is deduced as float . myFloat类型为std::shared_ptr<Node<float>> ,第一个函数参数的类型为std::shared_ptr<Node<T>> ,因此T推导为float

9.83 has type double , and the second function parameter has type T , so T is deduced as double. 9.83类型为double ,第二个函数参数的类型为T ,因此T推导为double。

Since template parameter T was deduced to be two different types, the overall deduction fails! 由于模板参数T被推断为两种不同的类型,因此总体扣除失败! When the same template parameter is deduced more than once, all the results must be identical. 当多次推导出相同的模板参数时,所有结果必须相同。

So what can you do to make this just work? 那么你能做些什么才能让它成功呢?

An unpleasant solution would be to leave the template alone and require callers to use it carefully. 一个令人不快的解决方案是单独留下模板并要求呼叫者小心使用它。 find<float>(myFloat, 9.83) would work by explicitly providing the template argument. find<float>(myFloat, 9.83)可以通过显式提供模板参数来工作。 find(myFloat, 9.83f) would work by changing the type of the second function argument. find(myFloat, 9.83f)可以通过改变第二个函数参数的类型来工作。 But it's better to make the template more flexible and friendlier. 但最好是使模板更灵活,更友好。

One simple fix is to just use two different template parameters. 一个简单的解决方法是只使用两个不同的模板参数。

template<class T, class U>
int find(std::shared_ptr<Node<T>> ptr, U val);

Then the function simply requires that the == operator works for the types T and U . 然后该函数只需要==运算符适用于类型TU

Or if you want the second function argument to be implicitly converted to the type used in the Node , you could intentionally turn the second use of T into a non-deduced context: 或者,如果您希望将第二个函数参数隐式转换为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);

By appearing left of :: , the second T is now a non-deduced context, so the expression find(myFloat, 9.83) will deduce T from the first argument only, resulting in T=float , then substitute into the template function declaration. 通过出现::左边,第二个T现在是一个非推导的上下文,因此表达式find(myFloat, 9.83)将仅从第一个参数推导出T ,导致T=float ,然后替换为模板函数声明。 typename identity<float>::type works out to float , so there will be an implicit conversion from the double literal 9.83 to float to call the function. typename identity<float>::type可以float ,因此会有一个从double literal 9.83float的隐式转换来调用该函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM