推导层次结构中模板参数的最低类型

时间:2018-08-02 23:46:17

标签: c++ templates generic-programming

我正在尝试弄乱模板,但是我很新。调用此函数时:

template <typename A, typename B, template<typename> typename Traversable, 
typename Fn>
auto map(const Traversable<A>& vec, Fn&& fn)
{
    Traversable<B> res{};
    for (A e : vec)
        res.push_back(fn(e));
    return res;
}

像这样:

vector<int> numbers { 1,2,3,4,5 };
auto numbers_times_two = map(numbers, [](auto a) { return a * 2; });

我得到一个模棱两可的错误:

Inferred conflicting substitutions for template parameter Traversable (std::vector and std::_Vector_alloc)

如我所见,编译器不知道是推论vector还是Traversable参数的超类。

在未明确指定模板参数的情况下,对map进行调用的最佳方法是 进行编译?适用于其他forward_listarray等其他可迭代对象的解决方案。

在这种情况下,是否有通用的解决方案来推导最具体的类而不是超类?

编辑:这仅在VS2017编译器中发生,但在g ++上有效。

因此,在使用Jarod42s answer之后,我创建了自己的容器类,只是为了查看错误是否仍然发生:

template <typename T>
class NewVec : public vector<T>
{
public:
    NewVec(initializer_list<T> il): vector<T>(il) {}
};

int main()
{
    NewVec<int> nv{ 1,2,3,4,5 };
    auto doubled = map(nv, [](auto a) { return a * 2; });
}

现在,该调用编译没有问题。但是vectorforward_list仍然会产生上述错误。

1 个答案:

答案 0 :(得分:1)

您可以使用:

template <template <typename, typename...> class Container, typename T, typename F>
auto map(const Container<T>& vec, F&& f)
{
    using RetType = std::decay_t<decltype(f(*vec.begin()))>;
    Container<RetType> res{};
    for (auto&& e : vec)
        res.push_back(f(e));
    return res;
}

Demo

所以所有类型都是可推论的。

理想情况下,我什至会删除T并使用rebind::other作为分配器提供的内容,但是容器不提供它。