c++ - 无法推断模板参数 'T'

标签 c++ templates predicate template-argument-deduction

我有非常简单的代码:

#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()函数,但无论出于何种原因,这都会破坏代码。我遇到的唯一错误是无法推断参数“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)

但是它按照我上面写的方式编译得很好。

那么是什么原因导致的呢?

最佳答案

模板参数T无法推断,因为 non-deduced context .

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)

模板参数推导不会在非推导上下文上执行,则 T仅在第三个函数参数上推导。鉴于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)

没有未推断的上下文和 T将根据所有函数参数进行推导。鉴于ex_count(v.begin(), v.end(), target); ,第一个和第二个函数参数 T将被推导为 list<int>::iterator ,在第 3 个时,它将被推导为 int ,它们是矛盾的。

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

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

关于c++ - 无法推断模板参数 'T',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63940030/

相关文章:

c++ - 在 native C++ 类中缓存字符串长度的后果?

angular - 如何在 Angular5 上从 express 渲染 html 模板

c++ - 模板化类型转换运算符 =

objective-c - NSPredicate: "Unable to parse the format string ' % @'"?

scheme - "Predicate"一词的起源是指 bool 函数吗?

c++ - 确保可变参数模板不包含重复项

c++ - 如何在删除 en 元素(双 for 循环)后正确指向 std::list?

c++ ->> 在 C++ 中做什么

c++ - <未解析的重载函数类型>