【问题标题】:Boost Multi-Index Custom Composite Key ComparerBoost 多索引自定义复合键比较器
【发布时间】:2009-08-24 21:09:49
【问题描述】:

我正在寻找使用复合键为提升 ordered_non_unique 索引编写自定义比较器。我不完全确定如何做到这一点。 Boost 有一个composite_key_comparer,但这对我不起作用,因为密钥成员的比较器之一取决于以前的成员。这是一个简化的示例,但是当second_ 为“A”时,我希望索引按third_ 降序排序,首先为third_ 保留0 值,并在所有其他情况下使用std::less。希望这是有道理的。我想打印下面的代码:

3,BLAH,A,0
5,BLAH,A,11
2,BLAH,A,10
4,BLAH,A,9
1,BLAH,A,8

代码将代替 WHAT GOES HERE???。感谢您的帮助。

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/key_extractors.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <iostream>

namespace bmi = boost::multi_index;
namespace bt = boost::tuples;

struct Widget
{
  Widget (const std::string& id, const std::string& f, char s, unsigned int t)
  : id_(id)
  , first_(f)
  , second_(s)
  , third_(t)
  { }

  ~Widget () { }

  std::string id_;
  std::string first_;
  char second_;
  unsigned int third_;
};

std::ostream& operator<< (std::ostream& os, const Widget& w)
{
  os << w.id_ << "," << w.first_ << "," << w.second_ << "," << w.third_;
  return os;
}

struct id_index { };
struct other_index { };

typedef bmi::composite_key<
  Widget*,
  bmi::member<Widget, std::string, &Widget::first_>,
  bmi::member<Widget, char, &Widget::second_>,
  bmi::member<Widget, unsigned int, &Widget::third_>
> other_key;

typedef bmi::multi_index_container<
  Widget*,
  bmi::indexed_by<
    bmi::ordered_unique<
      bmi::tag<id_index>,
      bmi::member<Widget, std::string, &Widget::id_>
    >,
    bmi::ordered_non_unique<
      bmi::tag<other_index>,
      other_key,
      ***************WHAT GOES HERE???***************
    >
  >
> widget_set;

typedef widget_set::index<other_index>::type widgets_by_other;
typedef widgets_by_other::iterator other_index_itr;

int main ()
{
  widget_set widgets;
  widgets_by_other& wbo_index = widgets.get<other_index>();
  Widget* w;

  w = new Widget("1", "BLAH", 'A', 8);
  widgets.insert(w);
  w = new Widget("2", "BLAH", 'A', 10);
  widgets.insert(w);
  w = new Widget("3", "BLAH", 'A', 0);
  widgets.insert(w);
  w = new Widget("4", "BLAH", 'A', 9);
  widgets.insert(w);
  w = new Widget("5", "BLAH", 'A', 11);
  widgets.insert(w);

  std::pair<other_index_itr,other_index_itr> range =
    wbo_index.equal_range(boost::make_tuple("BLAH", 'A'));

  while (range.first != range.second)
  {
    std::cout << *(*range.first) << std::endl;
    ++range.first;
  }

  return 0;
}

【问题讨论】:

    标签: c++ boost indexing


    【解决方案1】:

    我认为你已经碰壁了。

    您可以参考这里:Ordered Indices

    与 STL 一样,您实际上必须自己提供比较标准,因此您可以根据自己的需要对其进行调整。

    正如我链接的页面上所解释的(在“比较谓词”部分):

    有序索引规范的最后一部分是相关的比较谓词,它必须以小于的方式对键进行排序。

    因此,您的工作有两个方面:

    1. 您需要定义一个适用于您的类型的比较谓词
    2. 您需要向 Boost.MultiIndex 表明您希望使用此谓词来进行键的实际比较

    这是一个示例,但我不确定我是否完全理解您的要求,因此您可能需要检查它是否确实按您的意愿排序。

    struct WidgetComparer
    {
      bool operator()(const Widget& lhs, const Widget& rhs) const
      {
        if (lhs._second == 'A' && rhs._second == 'A')
        {
          return lhs._third == 0 || rhs._third < lhs._third;
        }
        else
        {
          return lhs._third < rhs._third;
        }
      } // operator()
    };
    

    然后,您只需完成索引。所以用 identity 替换“其他键”,用 WidgetComparer 替换“WHAT GOES HERE”。

    你来了!

    重要的一点是,您不应专注于容器的“关键”部分。键本身什么都不是,它是一对(键,比较谓词)进行实际排序。重点是文档中的键以增强代码重用(尤其是从已实现的比较谓词(如 std::less)中受益)。

    作为替代方案,您可以决定为您的 Widget 类编写“操作符

    希望有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-10-31
      • 2017-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-15
      • 1970-01-01
      相关资源
      最近更新 更多