无法推断模板参数 'T'

Cannot infer template argument '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";
}

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

我应该注意,除了我要问的问题之外,我不会寻求其他任何建议。代码过于复杂且毫无意义--我知道,但这不是我的设计。

有什么问题?

为清楚起见错误:

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

编辑:

有人告诉我,由于 :: 运算符无法推导它,但为什么此版本的代码仅在使用 :: 运算符时有效:

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

template <typename T>
int ex_count(typename list<T>::iterator v, typename list<T>::iterator v2, 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(), v.end(), 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

In the following cases, the types, templates, and non-type values that are used to compose P do not participate in template argument deduction, but instead use the template arguments that were either deduced elsewhere or explicitly specified. If a template parameter is used only in non-deduced contexts and is not explicitly specified, template argument deduction fails.

  1. The nested-name-specifier (everything to the left of the scope resolution operator ::) of a type that was specified using a 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)

模板参数推导不会在 non-deduced 上下文中执行,然后 T 将仅在第 3 个函数参数上推导。鉴于 ex_count(v.begin(), v.end(), target); T 将被推断为 int,并且 v.begin()v.end() 匹配类型 list<int>::iterator,一切都很好。

对于

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

没有 non-deduced 上下文,T 将根据所有函数参数推导出来。给定 ex_count(v.begin(), v.end(), target);,第一个和第二个函数参数 T 将被推断为 list<int>::iterator,第三个将被推断为 int,它们是冲突的。

如果你把模板参数分开就没问题了。

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