我想编写一个简单的函数来简化std::transform
以便在单个向量上进行转换。
到目前为止我所拥有的:
template<typename T>
void transform(std::vector<T> &vec, const std::function<T(const T &)> &fun) {
std::transform(std::begin(vec), std::end(vec), std::begin(vec), fun);
}
现在,当我想使用此功能时,我可以编写,例如:
transform<int>(vec, my_function);
但是我更愿意使用
transform(vec, my_function);
有没有办法调整我的代码以自动推断类型?
错误:
no matching function for call to 'transform' and note: candidate template ignored: could not match 'function<type-parameter-0-0 (const type-parameter-0-0 &)>' against '(lambda at [...]
答案 0 :(得分:3)
似乎您正在使用lambda作为参数; lambda可以转换为std::function
,但是在template argument deduction中不会考虑隐式转换,这就是失败的原因。
类型推导不考虑隐式转换(上面列出的类型调整除外):这是超载解析的工作,稍后会发生。
您可以在传递时显式使用static_cast
将lambda转换为std::function
,或停止使用std::function
。例如
template<typename T, typename F>
void transform(std::vector<T> &vec, F fun) {
std::transform(std::begin(vec), std::end(vec), std::begin(vec), fun);
}
答案 1 :(得分:1)
如果出于某种原因需要使用std::function
参数,另一种方法是通过将T
移到非推导上下文中来禁用其中的T
类型推导: / p>
template<typename T>
struct Identity { using Type = T; };
template<typename T>
using Id = typename Identity<T>::Type;
template<typename T>
void transform(std::vector<T>&, const std::function<Id<T>(const Id<T>&)>&);
答案 2 :(得分:0)
您过度约束了两个参数,并尝试同时使用template-deduction和隐式转换作为第二个参数,这是行不通的。无需这样做,可以选择使用SFINAE,使事情正常,高效和灵活地运行:
using std::begin;
using std::end;
template <class Range, class F>
auto transform(Range&& range, F f)
noexcept(noexcept(std::transform(begin(range), end(range), begin(range), f)))
-> decltype(std::transform(begin(range), end(range), begin(range), f))
{ return std::transform(begin(range), end(range), begin(range), f); }
是,复制了功能对象。如果您不希望这样做,只需使用std::reference_wrapper
传递std::ref
即可,就像标准库算法一样。