基于getter成员函数对STL容器进行排序,无需编写额外代码
sort a STL container based on a getter member function, with no extra code written
让我们考虑以下代码示例:
// Example program
#include <iostream>
#include <string>
#include <algorithm>
class A
{
public:
A( const std::string& name ) : name( name ) {}
inline const std::string& getName() const { return name; }
private:
std::string name;
};
int main()
{
std::vector<A> v;
v.push_back( A("b") );
v.push_back( A("a") );
// want to sort the container, based on it's name!
}
我知道如何做到这一点(要么定义一个内部或外部operator<
,要么声明一个提供operator()
的函子结构/类,并将其传递给std::sort
函数),例如:
bool operator<( const A& a ) const
{
return getName() < a.getName();
}
然而,每当我想根据包含的类属性对容器进行排序时,尤其是当类为其提供getter函数时,我就懒得这样做了
是否可以请求基于类成员函数结果值进行排序(显然,如果这个函数有可用的比较器)?
类似于:
std::sort( v.begin(), v.end(), &(A::getName) );
不必声明新的运算符或函子?
可选问题:若矢量包含指针(std::vector<A*> v
)。。。一行语句可以根据A::getName
结果对其进行排序吗?
您可以使用lambda函数对向量进行排序:
std::sort(v.begin(), v.end(), [] (A const& a, A const& b) {
return a.getName() < b.getName();
});
它比您的版本长,但在调用sort
之前您不需要编写任何内容。
如果你需要经常做这种事情,你可以把所有的东西都放在一个小函数中(并允许它同时适用于A
、A*
和智能指针),它使用mem_fn
(多亏了@T.C.):
template <typename T, typename R>
struct cmp_attr {
using fun_t = R (T::*) () const;
cmp_attr (fun_t g) : _g(g) { }
template <typename U>
bool operator() (U const& a, U const& b) const {
auto fn = std::mem_fn(_g);
return fn(a) < fn(b);
}
private:
fun_t _g;
};
// Utility function to have template parameters deduced, a like std::make_pair
template<typename T, typename R>
auto make_cmp_attr (R (T::*g) () const) {
return cmp_attr<T, R>(g);
}
然后:
struct A { const std::string& getName(); }
struct B: public A { }
std::vector<A> v1; // vector of A
std::sort(v1.begin(), v1.end(), make_cmp_attr(&A::getName));
std::vector<A*> v2; // vector of A*
std::sort(v2.begin(), v2.end(), make_cmp_attr(&A::getName));
std::vector<B> v3; // vector of child class
std::sort(v3.begin(), v3.end(), make_cmp_attr(&A::getName));
std::vector<B*> v4; // vector of pointer of child class
std::sort(v4.begin(), v4.end(), make_cmp_attr(&A::getName));
我建议不要因为有一个特定的用例就重载operator<
。将排序逻辑放在需要的地方;它不是类型的一部分。
如果你想定期按投影排序,那么写一个小助手可能是值得的:
template <typename C, typename R>
struct SortByPred
{
using P = R (C::*)() const;
P const p_;
SortByPred(P p) : p_(p) {}
template <typename T>
bool operator()(T const & lhs, T const & rhs) const
{
return (lhs.*p_)() < (rhs.*p_)();
}
};
template <typename C, typename R>
SortByPred<C, R> SortBy(R (C::*p)() const)
{
return SortByPred<C, R>(p);
}
用法:
std::sort(v.begin(), v.end(), SortBy(&A::getName));
相关文章:
- 我不明白这段代码是如何对这个pythonlist()进行排序的,也不明白如何用C++中的向量来重现它
- 为什么我需要C++中不同的排序格式来对这个USACO代码上的数组和优先级队列进行排序
- 无法在我的堆排序代码中找到错误.无法正确执行.C++
- 使用 std::vector C++快速排序,EXC_BAD_ACCESS代码 2
- 在实现合并排序代码时无法计算所有反转
- 我的C++合并排序代码不起作用。我在这里错过了什么?
- 我怎么不能按课程代码的降序对数字进行排序
- C++17.处理使用 auto 相关的模板参数.代码排序困难
- 排序程序的意外错误代码
- 为什么我的代码没有对数组中第二个索引上的数据进行排序?
- 为什么此代码上的排序算法不调用类的交换版本?
- 我的选择排序代码是否存在导致它跳过数组中的元素的问题?
- 此气泡排序代码中的错误是什么?
- 堆排序,我无法弄清楚我的代码出了什么问题,输出顺序不正确
- 合并排序代码中的分段错误
- 我的C++合并排序代码有什么问题?
- 添加气泡排序代码以排列列表
- C 代码:关于排序的搜索测试示例
- 我写了一个快速的排序代码,逻辑似乎很正确,但是控制台上没有输出
- shell将伪代码排序为c++代码