编译器不推断模板参数(映射std :: vector-> std :: vector) [英] Compiler does not deduce template parameters (map std::vector -> std::vector)

查看:113
本文介绍了编译器不推断模板参数(映射std :: vector-> std :: vector)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下模板。

template<typename T, typename U>
std::vector<U> map(const std::vector<T> &v, std::function<U(const T&)> f) {
    std::vector<U> res;
    res.reserve(v.size());
    std::transform(std::begin(v), std::end(v), std::end(res), f);
    return res;
}

在我的代码中使用它时,请指定模板参数。为什么编译器无法为我推断出这一点?

When I use it in my code I have the specify the template parameters. Why is the compiler not able to deduce this for me? How do I have to change my template definition to make this work?

vector<int> numbers = { 1, 3, 5 };

// vector<string> strings = map(numbers, [] (int x) { return string(x,'X'); });

vector<string> strings = map<int, string>(numbers, [] (int x) { return string(x,'X'); });

可运行代码: http://ideone.com/FjGnxd

此问题的原始代码来自此处:返回转化后的容器的类似于std :: transform的函数

The original code in this question comes from here: The std::transform-like function that returns transformed container

推荐答案

您的函数需要一个 std :: function 参数,但您使用的是lambda表达式代替。两者不是同一类型。 Lambda可以转换为 std :: function ,但模板参数推导需要完全匹配,并且不考虑用户定义的转换。因此,扣除失败。

Your function expects an std::function argument, but you're calling it with a lambda expression instead. The two are not the same type. A lambda is convertible to std::function, but template argument deduction requires exact matches and user defined conversions are not considered. Hence the deduction failure.

如果您实际上将 std :: function 传递给<$ c $,则扣除确实起作用c> map()。

Deduction does work if you actually pass an std::function to map().

std::function<string(int const&)> fn = [] (int x) { return string(x,'X'); };
vector<string> strings = map(numbers, fn);

实时演示

避免指定模板参数的一种可能的解决方法是修改函数以接受任何类型的可调用对象,而不是 std :: function 对象。

One possible workaround to avoid having to specify the template arguments is to modify the function to accept any kind of callable, rather than an std::function object.

template<typename T, typename Func>
std::vector<typename std::result_of<Func(T)>::type>
    map(const std::vector<T> &v, Func f) {
        // ...
    }

同一个想法的另一个版本,使用 decltype declval 代替 result_of

Another version of the same idea, using decltype and declval instead of result_of

template<typename T, typename Func>
std::vector<decltype(std::declval<Func>()(std::declval<T>()))>
    map(const std::vector<T> &v, Func f) {
        // ...
    }

最后,使用尾随返回类型

Finally, using a trailing return type

template<typename T, typename Func>
auto map(const std::vector<T> &v, Func f) 
  -> std::vector<decltype(f(v[0]))> {
        // ...
    }

实时演示

这篇关于编译器不推断模板参数(映射std :: vector-> std :: vector)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆