【问题标题】:Can I use boost bind to define a comparator for sorting an STL list?我可以使用 boost bind 定义一个比较器来对 STL 列表进行排序吗?
【发布时间】:2014-04-16 00:05:59
【问题描述】:

我有一个std::list,我想使用从一组中选择的比较器进行排序。我想使用 boost bind 来定义比较器,这样我就可以为每个比较器隐式定义一个函数。大意是:

struct MyStruct { int a; int b };
std::list<MyStruct> myList;
...
myList.sort(_1.a < _2.a);

以上代码无法编译。我的问题是,如何使用 boost 内联定义比较器?

【问题讨论】:

  • 只是好奇...你有 C++11 编译器吗?有什么理由不想使用 lambda?
  • 不幸的是,我没有 c++11 :(
  • 试试myList.sort(bind(&amp;MyStruct::a, _1) &lt; bind(&amp;MyStruct::b, _2))。该用法记录在here
  • 您确定要订购吗? _1.a &lt; _2.b 不是一个定义明确的严格弱排序。示例:(0,1)(0,2) 小和大...

标签: c++ boost


【解决方案1】:

我会使用 Boost Phoenix:

#include <boost/phoenix.hpp>
#include <list>

namespace phx = boost::phoenix;
using namespace phx::arg_names;

struct MyStruct { int a; int b; };

int main()
{
    std::list<MyStruct> myList;
    //...
    myList.sort(phx::bind(&MyStruct::a, arg1) < phx::bind(&MyStruct::b, arg2));
}

请注意,比较不同的字段似乎非常奇怪(除非字段具有某种保证的冗余关系(例如:它们始终相等))它不会满足严格弱总排序的要求 - 大多数 STL 容器都需要/采用比较器的算法。

避免两者

  • 比较器的详细程度,以及
  • 左侧/右侧具有不同访问器的风险

我通常使用助手(c++03):

#include <boost/bind.hpp>
#include <list>

template <typename F>
struct compare_by_impl {
    compare_by_impl(F f = F()) : _f(f) {}

    template <typename T, typename U>
    bool operator()(T const& a, U const& b) const {
        return _f(a) < _f(b);
    }
  private:
    F _f;
};

template <typename Accessor>
compare_by_impl<Accessor> comparer_by(Accessor f) {
    return compare_by_impl<Accessor>(f);
}

struct MyStruct { int a; int b; };

int main()
{
    std::list<MyStruct> myList;
    //...
    myList.sort(comparer_by(boost::mem_fn(&MyStruct::a)));
}

这不再使用 Boost Phoenix。看到它Live on Coliru

在此处查看更新的 c++11 版本:How to implement a lambda function for a sort algorithm involving object members, indirection, and casting?

【讨论】:

  • @Danvil 嗯?这不是那么多,真的。我也在 c++11 中使用了 compare_by_impl 之类的工具,它与 c++11 功能的编译器支持无关。而且它比 c++11 lambda 简洁得多。另外,请注意 Boost Phoenix/Lambda 表达式是多态的。尝试使用 c++11 lambdas...
  • 我没有冒犯的意思。不错的答案!只是觉得list.sort([](const MyStruct&amp; a, const MyStruct&amp; b) { return a.a &lt; b.b; }); 看起来更干净。
  • @Danvil 老实说,我不会让它通过代码审查。我同意这是 OP 的代码,但它似乎坏了。出于这个确切原因,我需要一个更干燥的版本(无需重复 .a 取消引用或 const MyStruct&amp;)。 Lambdas 虽然简洁,但在我阅读时仍然需要耗费脑力。
  • 我很抱歉。最初的比较是错字的。我没有故意比较两个不同的领域。
  • @MM。干杯:/没问题。它实际上强调了为什么要避免代码中的重复。更少的代码,更少的错误,代码重复:玩火。
猜你喜欢
  • 2020-07-09
  • 2018-09-10
  • 2020-07-11
  • 2019-05-06
  • 2011-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-13
相关资源
最近更新 更多