C++函数对象 的模板参数 技巧
假定有两组数,需要将对应的元素相加,用stl咋做
void fooTransform()
{
std::vector<int> va{
1,2,3,4,5
};
std::vector<int> vb{
3,6,8,10,15
};
std::vector<int> r(vb.size());
range::transform(va, vb, r.begin(), std::plus<int>());
for (int i: r)
{
std::cout << i << std::endl;
}
}
然而看到了吗,上文中的函数对象必须用类型int实例化为std::plus
struct Plus {
template<class T>
T operator()(const T& l, const T&r)const
{
return l + r;
}
};
现在上述代码可修改为
void fooTransform()
{
std::vector<int> va{1, 2, 3, 4, 5};
std::vector<int> vb{3, 6, 8, 10, 15};
std::vector<int> r(vb.size());
range::transform(va, vb, r.begin(), Plus());
for (int i : r) {
std::cout << i << std::endl;
}
}
看,现在不再需要给Plus类用 int 实例化了,只需要Plus()便可,方便许多。然而使用新的方法并不是没有代价的,比如假定我们要将一组数加7,用std::plus的实现如下
void TransformPlus7()
{
std::vector<int> va{
1,2,3,4,5
};
std::vector<int> vb{
3,6,8,10,15
};
range::transform(va, vb.begin(), std::bind1st(std::plus<int>(), 7));
for (int i: vb)
{
std::cout << i << std::endl;
}
}
我们只需要使用std::bind1st将 7 绑定为std::plus
可以使用std::bind绑定, tansform那行可替换为 using namespace std::placeholders; range::transform(va, vb.begin(), std::bind(Plus(), 7, _1)); 这时是可以编译通过的。
然而对于需要绑定的情况,更好的做法是使用lambda, 比如 std::bind1st(std::plus
你或许会问为啥标准库的std::plus不支持不带类型的实例化呢,标准委员会意识到了该问题,在C++14中,std::plus
建议优先使用不带具体类型的函数对象,如果需要绑定,请使用lambda代替,同时,使用C++14和C++17吧,写优雅的代码更容易,也更易读。