无法推断出模板类型

时间:2017-03-17 18:08:00

标签: c++ templates

我有一个(简化的)函数Foo

template<typename It, typename T>
void Foo(It begin, It end, T&& CallBar)
{
    CallBar(begin, end);
}

另一个简化的功能吧

template<typename It>
It Bar(It begin, It end)
{
    return begin;
}

当我以下列方式调用这两个函数时

std::vector<int> v{ 3, 8, 2, 5, 1, 4, 7, 6 };
Foo(v.begin(), v.end(), Bar);

我收到错误

  

'declaration':无法推断'identifier'的模板参数

我还需要指定什么来使其编译?

3 个答案:

答案 0 :(得分:6)

这里的问题是,由于Bar是一个功能模板,因此它不知道您想要哪个Bar。你必须告诉它使用什么版本的Bar。一种方法是指定模板类型。你可以这样做:

Foo(v.begin(), v.end(), Bar<decltype(v.begin())>);

如果您不想指定模板类型,说实话,有点脆弱,那么我们可以将调用包装在lambda中Bar。这将允许编译器为我们执行所有类型推导,这更容易维护。例如,如果您更改迭代器类型,则无需更改以前的解决方案。感谢0x499602D2,这将是

Foo(v.begin(),v.end(),[](auto b,auto e){return Bar(b,e);})

答案 1 :(得分:2)

  

我还需要指定什么来使其编译?

以示例

template<typename It>
void Foo(It begin, It end, It(* CallBar)(It, It))
{
    CallBar(begin, end);
}

答案 2 :(得分:2)

您可以使用template templates来帮助解决此问题。据我所知,它要求您将Bar函数包装在仿函数中。通过首先放置仿函数模板参数,您可以指定它并让迭代器类型被推导出来。

#include <vector>

// T is a type that takes a 'class' template argument
template<template<class> class T, class It>
void Foo(It begin, It end)
{
    T<It>()(begin, end);
}

template<typename It>
struct Bar
{
    It operator()(It begin, It end)
    {
        return begin;
    }
};

int main()
{
    std::vector<int> v{ 3, 8, 2, 5, 1, 4, 7, 6 };
    Foo<Bar>(v.begin(), v.end());
    return 0;
}