我有以下模板
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; }
当我在我的代码中使用它,我有指定模板参数.为什么编译器不能为我推断这个?如何更改我的模板定义以使其工作?
vector<int> numbers = { 1,3,5 }; // vector<string> strings = map(numbers,[] (int x) { return string(x,'X'); }); vector<string> strings = map<int,string>(numbers,'X'); });
可运行代码:http://ideone.com/FjGnxd
这个问题的原始代码来自于:The std::transform-like function that returns transformed container
解决方法
你的函数需要一个std :: function参数,但是你用lambda表达式来调用它.两者不一样.一个lambda可以转换成std :: function,但是模板参数的扣除需要精确的匹配,不考虑用户定义的转换.因此扣除失败.
如果您实际将std ::函数传递给map(),则扣除工作正常.
std::function<string(int const&)> fn = [] (int x) { return string(x,'X'); }; vector<string> strings = map(numbers,fn);
避免必须指定模板参数的一种可能的解决方法是修改函数以接受任何类型的可调用,而不是std :: function对象.
template<typename T,typename Func> std::vector<typename std::result_of<Func(T)>::type> map(const std::vector<T> &v,Func f) { // ... }
同一个想法的另一个版本,使用decltype和declare而不是result_of
template<typename T,typename Func> std::vector<decltype(std::declval<Func>()(std::declval<T>()))> map(const std::vector<T> &v,Func f) { // ... }
最后,使用尾随返回类型
template<typename T,typename Func> auto map(const std::vector<T> &v,Func f) -> std::vector<decltype(f(v[0]))> { // ... }