无法推断模板参数“ T”

问题描述

我有非常简单的代码

#include <iostream>
#include <list>
using namespace std;

template <typename T,typename Function>
int ex_count(typename list<T>::iterator v,typename list<T>::iterator v2,Function match)
{
    int count = 0;
    while(v != v2)
    {
        if(match(*v))
            count++;
        ++v;
    }
    return count;
}

template <typename T>
class ex_eq
{
    public:
    ex_eq(const T &n_target = T())
    {
        target = n_target;
    }
    bool operator() (const T &a)
    {
        return a == target;
    }
    private:
    T target;
};

int main() 
{
    list<int> v;
    list<int>::iterator iv;
    int value;
    while (cin >> value)
        v.push_back(value);
    int target = *v.begin();
    int N = ex_count(v.begin(),v.end(),ex_eq<int>(target));
    cout << "Found " << N << " instances of " << target << "\n";
}

我最近在Function match函数中实现了谓词对象int ex_count(),但是由于任何原因,这都会破坏代码。我得到的唯一错误是,对于int ex_count(),无法推断出参数'T',即使使用常量而不是对象(Function match)也可以正常工作。

我应该注意,除了我要问的问题以外,我没有在寻求其他建议。代码过于复杂和毫无意义-我知道,但这不是我的设计。

出什么问题了?

为清楚起见,出现错误

note: candidate template ignored: Couldn't infer template argument 'T'
int ex_count(typename list<T>::iterator v,Function match)

编辑:

有人告诉我,由于::运算符而无法推断出它,但是为什么为什么此版本的代码仅在使用::运算符时才起作用:

#include <iostream>
#include <list>
using namespace std;

template <typename T>
int ex_count(typename list<T>::iterator v,T target)
{
    int count = 0;
    while(v != v2)
    {
        if(*v == target)
            ++count;
        ++v;
    }
    return count;
}

int main() {
    list<int> v;
    list<int>::iterator iv;
    int value;
    while (cin >> value)
        v.push_back(value);
    int target = *v.begin();
    int N = ex_count(v.begin(),target);
    cout << "Found " << N << " instances of " << target << "\n";
}

此版本不使用函数对象,而仅使用target。但是,如果我尝试将ex_count的参数从list<T>::iterator更改为T,则会收到错误消息:

note: candidate template ignored: deduced conflicting types for parameter 'T'
      ('std::__1::__list_iterator<int,void *>' vs. 'int')
int ex_count(T v,T v2,T target)

但是它的编译方式与上面我写的一样好。

那是什么原因造成的?

解决方法

由于non-deduced context而无法推导出模板参数T

在以下情况下,用于构成 P 的类型,模板和非类型值不参与模板自变量的推导,而是使用在其他地方推导的模板自变量或明确指定。如果仅在非推导上下文中使用模板参数并且未明确指定模板参数,则模板参数推导将失败。

  1. 使用qualified-id指定的类型的嵌套名称说明符(范围解析运算符::的所有内容):

您可以显式指定模板参数以绕过模板参数推导,

int N = ex_count<int>(v.begin(),v.end(),ex_eq<int>(target));

或更改功能模板以直接将迭代器类型指定为模板参数。 (它可以与任何迭代器一起使用,包括原始指针。)

template <typename Iterator,typename Function>
int ex_count(Iterator v,Iterator v2,Function match)
{
    int count = 0;
    while(v != v2)
    {
        if(match(*v))
            count++;
        ++v;
    }
    return count;
}

编辑

对于

template <typename T>
int ex_count(typename list<T>::iterator v,typename list<T>::iterator v2,T target)

不会在非推导上下文中执行模板参数推导,然后T仅在第三函数参数上推导。给定ex_count(v.begin(),target); T会被归为int,并且v.begin()v.end()与类型list<int>::iterator匹配,一切都很好。

对于

template <typename T>
int ex_count(T v,T v2,T target)

没有非推论上下文,并且将在所有函数参数上推论T。给定ex_count(v.begin(),target);,在第一个和第二个函数参数T上将推论为list<int>::iterator,在第三个函数参数上将其推论为int,它们是冲突的。 / p>

如果您将模板参数分开,那就没问题了。

template <typename Iterator,typename T>
int ex_count(Iterator v,T target)