如何在C++20 Ranges中结合投影与变换操作?无需Lambda或仿函数实现基于投影成员函数结果的排序
不用Lambda/仿函数实现自定义投影排序
当然可以!你完全可以避开Lambda和自定义仿函数来实现这个基于Distance函数的排序逻辑,下面给你两种简洁可行的方案:
方案1:自定义普通投影函数(最直观易读)
这是最直接的方式——我们只需要写一个普通的函数,把S类型对象转换成排序需要的键值(也就是Distance(s.val)的结果),然后把这个函数的指针传给std::ranges::sort的投影参数即可:
#include <algorithm> #include <vector> #include <cstdlib> struct S{ int val; }; int origin = 47; int Distance(int val){ return std::abs(val - origin); } // 自定义普通投影函数,无Lambda、无仿函数 int S_projection(const S& s) { return Distance(s.val); } void my_sort(std::vector<S> ss) { // 直接传入投影函数的指针 std::ranges::sort(ss, std::greater<>{}, &S_projection); }
这个方案的优势在于代码清晰易懂,后续维护起来也很方便,完全符合你的需求。
方案2:使用std::bind实现函数组合(无需额外定义函数)
如果你不想额外定义一个函数,可以用标准库的std::bind来组合成员访问和Distance函数,生成符合要求的投影可调用对象:
#include <algorithm> #include <vector> #include <functional> #include <cstdlib> struct S{ int val; }; int origin = 47; int Distance(int val){ return std::abs(val - origin); } void my_sort(std::vector<S> ss) { // 用两层bind组合成员访问和Distance函数 std::ranges::sort(ss, std::greater<>{}, std::bind(Distance, std::bind(&S::val, std::placeholders::_1))); }
这里的逻辑是:
- 内层
std::bind(&S::val, std::placeholders::_1)会接受一个S对象,返回其val成员; - 外层
std::bind(Distance, ...)会把内层的结果作为参数传给Distance,最终得到我们需要的排序键值。
两种方案都能完美实现你想要的排序逻辑,你可以根据自己的代码风格和场景选择合适的方式。
内容的提问来源于stack exchange,提问作者NoSenseEtAl
相关产品推荐
相关产品推荐

