[英]Using STL algorithms on unary functions
So I often want to perform some STL algorithm on a range of elements and instead of a comparison function, I would like to pass a unary function f.所以我经常想对一系列元素执行一些 STL 算法,而不是比较 function,我想传递一元 function f。
For example I would like to write something like this例如我想写这样的东西
std::max_element(begin(range), end(range), f);
to find the maximum element in the range after applying f.在应用 f 后找到范围内的最大元素。 My current workaround looks something like that:
我目前的解决方法看起来像这样:
std::max_element(begin(range), end(range, [&f](auto a, auto b){ return f(a) < f(b); });
At first glance, this may look like no problem.乍一看,这似乎没有问题。 But f could be a lambda expression itself or in another way more complicate than just f.
但是 f 可能是 lambda 表达式本身,或者以另一种方式比 f 更复杂。 I have two problem with that piece of code: a) It is error prone because one could accidently write f(a) < f(a) (especially if more complicated and one used copy and past).
我对那段代码有两个问题:a)它很容易出错,因为人们可能会不小心写出 f(a) < f(a) (特别是如果更复杂并且使用了副本和过去)。 This is the problem of code duplication b) It does not express the intent very well.
这是代码重复的问题 b) 它没有很好地表达意图。 If I want to sort by a function, I do not want to deal with a comparison.
如果我想按 function 排序,我不想处理比较。
Unfortunately I have not found a good solution to this kind of problem in the standard library (or even boost), so I would like to ask you what your solution to this problem is.不幸的是,我在标准库(甚至是boost)中没有找到解决这类问题的好方法,所以我想问一下你对这个问题的解决方案是什么。 Is there any reason for the non-existence of this overload in the algorithms?
算法中不存在这种重载有什么原因吗?
Using c++ 20's ranges you can do:使用 c++ 20 的范围,您可以:
std::ranges::max_element(range | std::views::transform(f));
One thing you can do is create your own generic comparator that accepts a unary function to perform a transform:您可以做的一件事是创建自己的通用比较器,该比较器接受一元 function 来执行转换:
// Generic comparator
template<typename T, typename F>
struct transform_comparator_type
{
transform_comparator_type(F f): f(f) {}
bool operator()(T const& a, T const& b) const { return f(a) < f(b); }
F f;
};
// Helper function to deduce the type of F
template<typename T, typename F>
auto transform_comparator(F f)
{
return transform_comparator_type<T, F>(f);
}
int main()
{
std::vector<int> v{1, 4, 3, 6, 0};
auto e = std::max_element(std::begin(v), std::end(v),
transform_comparator<int>([v](int i){ return 2 * i; }));
// etc...
}
Edited to add:编辑添加:
The type can actually be deduced from the return type of the supplied transform function, so you don't need the helper function.该类型实际上可以从提供的变换 function 的返回类型推导出来,因此您不需要帮助器 function。 You can do this instead:
你可以这样做:
template<typename F>
struct transform_comparator
{
using T = decltype(F()({})); // deduce T from return type of F
transform_comparator(F f): f(f) {}
bool operator()(T const& a, T const& b) const { return f(a) < f(b); }
F f;
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.