是否可以以优雅的方式在向量上运行标准算法<MyType>?

Is it possible to run standard algorithms on vector<MyType> in an elegant way?

本文关键字:标准 lt 算法 MyType gt 运行 方式 向量 是否      更新时间:2023-10-16

我知道如果我有一个vector<int>,我可以在它上面运行这样的算法:

int max = *max_element(myints.begin(), myints.end());

但是如果我有一个vector<MyStruct>,其中一个结构体中的字段是int,该怎么办?有没有一种优雅的方法可以在所有结构体中的整数上运行算法?

为max_element:

提供比较器
MyStruct max = *max_element(v.begin(), v.end(),
    [](const MyStruct & lhs, const MyStruct & rhs) { return lhs.theInt < rhs.theInt; });

如果你的编译器还不支持lambdas,你将不得不编写一个单独的函数或函数对象类。

或者,如果你重载operator<让你的类做同样的比较,那么你可以简单地这样做:

MyStruct max = *max_element(v.begin(), v.end());

这取决于你对"优雅"的定义,但是,是的,这是可以做到的。事实上,在许多不同的方面。

在标准c++中,可以使用函子:

#include <algorithm>
#include <vector>
#include <functional>
using namespace std;
class Gizmo
{
public:
    int n_;
};
class BiggestGizmo : public std::binary_function<bool, Gizmo, Gizmo>
{
public:
    bool operator()(const Gizmo& lhs, const Gizmo& rhs) const
    {
        return lhs.n_ > rhs.n_;
    }
};
int main()
{
    typedef vector<Gizmo> Gizmos;
    Gizmos gizmos;
    Gizmos::const_iterator it = max_element(gizmos.begin(), gizmos.end(), BiggestGizmo());
}
在c++ 0X中,您可以使用Lambda:
#include <algorithm>
#include <vector>
using namespace std;
class Gizmo
{
public:
    int n_;
};
int main()
{
    typedef vector<Gizmo> Gizmos;
    Gizmos gizmos;
    Gizmos::const_iterator it = max_element(gizmos.begin(), gizmos.end(), [](const Gizmo& lhs, const Gizmo& rhs) -> bool
    {
        return lhs.n_ > rhs.n_;
    });
}

另一种选择:您可以编写自己的迭代器类,其引用类型和值类型为int&int,但它在引用类型为MyStruct&的迭代器上运行,提供对该字段的访问。

这比仅仅为max_element提供一个额外的比较器要多一点工作,但是如果你做了一次,那么你已经为所有的算法做了,而不仅仅是那些通过比较器起作用的算法。如果您可以使用它,boost::transform_iterator将为您处理样板文件。

boost::transform_iterator不允许您从实例中获得底层迭代器,但在vector的情况下,这无关紧要,因为它是随机访问的,因此计算距离并将其应用于begin()迭代器是有效的。

对于结构体,可以定义比较函数或比较对象。您还可以为您的结构定义<操作符。下面是一个例子

正如您在其中一个评论中所说的,您有许多类成员,并且希望在算法中分别处理每个成员。你会得到各种各样的可能性

  • lambdas无处不在(无论是Phoenix还是c++ 11)
  • 每个case的函子
  • 每个case的成员函数

只有当我需要重复时,我才会选择后两个解决方案lambda在不同的地方(或者如果我必须使用Phoenix,但这是这是个人的事情)。

struct Foo {
  int a;
  int b;
  bool less_than_by_a(const Foo&) const;
  bool less_than_by_b(const Foo&) const;
};
std::max_element(begin, end, std::mem_fun_ref(&Foo::less_than_by_a));
std::max_element(begin, end, std::mem_fun_ref(&Foo::less_than_by_b));