如何使用/创建boost :: multi_index? [英] How to use/create boost::multi_index?

查看:107
本文介绍了如何使用/创建boost :: multi_index?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人可以向我详细解释如何使用boost::multi_index创建多索引映射吗?我在网上看到了很多示例,在提升页面上也看到了,但我听不懂.我想将多个int/longs作为键映射类对象指针.有人可以帮我理解这一点吗?

Can someone explain to me in detail how to create a multi index map using boost::multi_index? I saw many examples online and also the boost page, but I could not understand it. I would want to map class object pointer by multiple int/longs as keys. Can someone please help me with understanding this?

我有一个类X和该类的多个属性,分别是long longlongintint.我想将属性long longlongintint存储为映射到->< X的指针的键.

I have a class X and multiple properties of the class which are long long, long, int, int. I want to store properties long long, long, int, int as keys to map to -> <pointer to X>.

我希望能够在给定任何属性的情况下查找指针.一些属性对于X的每个对象都是唯一的,而某些属性不是唯一的.

I want to be able to look up the pointer given any property. Some of the properties are unique to each object of X and some are not unique.

推荐答案

Boost.Multi-index offers an extremely customisable interface, at the cost of offering an extremely complex interface, so it's easy to understand why you're stuck.

我将提供一个注释示例,该示例应与您的用例相匹配.

I'll present a commented example which should match your use case.

首先,我们的数据:

struct X
{
  long long l; // assume unique
  int i1; // assume unique
  int i2; // assume non-unique
  // plus any ohter data you have in your class X
};

接下来,我们将为我们希望容器具有的每个索引准备一个标签.标记不是严格必需的(索引可以按其顺序访问),但是为每个索引提供名称更方便:

Next, we'll prepare one tag for each index which we want the container to have. Tags aren't strictly necessary (indexes can be accessed by their order), but it's more convenient to provide a name for each index:

struct IndexByL {};
struct IndexByI1 {};
struct IndexByI2 {};

现在,我们需要将容器的类型放在一起:

Now, we have what we need to put together the type of the container:

using Container = boost::multi_index_container<
  X*, // the data type stored
  boost::multi_index::indexed_by< // list of indexes
    boost::multi_index::hashed_unique<  //hashed index over 'l'
      boost::multi_index::tag<IndexByL>, // give that index a name
      boost::multi_index::member<X, long long, &X::l> // what will be the index's key
    >,
    boost::multi_index::ordered_unique<  //ordered index over 'i1'
      boost::multi_index::tag<IndexByI1>, // give that index a name
      boost::multi_index::member<X, int, &X::i1> // what will be the index's key
    >,
    boost::multi_index::hashed_non_unique<  //hashed non-unique index over 'i2'
      boost::multi_index::tag<IndexByI2>, // give that index a name
      boost::multi_index::member<X, int, &X::i2> // what will be the index's key
    >
  >
>;

就是这样,我们有一个容器.接下来,这是我们的使用方式:

That's it, we have a container. Next, here's how we can use it:

Container c;  // empty container
X x1{...}, x2{...}, x3{...};  // some data

// Insert some elements
auto& indexByL = c.get<IndexByL>(); // here's where index tags (=names) come in handy
indexByL.insert(&x1);
indexByL.insert(&x2);
indexByL.insert(&x3);

// Look up by i1
auto& indexByI1 = c.get<IndexByI1>();
auto itFound = indexByI1.find(42);
if (itFound != indexByI1.end())
{
  X *x = *itFound;
}

// Look up by i2
auto& indexByI2 = c.get<IndexByI2>();
size_t numberOfHundreds = indexByI2.count(100);

[实时示例]

现在,有关野兽如何运作的一些散文.

And now, some prose about how the beast works in general.

您可以通过指定要存储的对象类型(在您的情况下为X*)以及一个或多个可用于访问存储的对象的索引来定义多索引容器.将索引视为访问数据的接口.

You define a multi-index container by specifying the type of objects it will store (X* in your case), and one or more indexes which can be used to access the stored objects. Think of indexes as interfaces for accessing the data.

索引可以是不同的种类:

Indexes can be of different kinds:

  • 基于键排序的索引(请考虑std::setstd::map)
  • 基于键的排名的索引(认为相同,并且可以轻松访问第 n 个元素)
  • 基于对键进行哈希处理的索引(请考虑std::unordered_setstd::unordered_map)
  • 基于稳定访问的索引(请考虑std::list)
  • 基于稳定顺序的随机访问的索引(请考虑std::vector)
  • Indexes based on ordering by a key (think std::set or std::map)
  • Indexes based on ranking by a key (think the same plus easy access to nth element)
  • Indexes based on hashing a key (think std::unordered_set or std::unordered_map)
  • Indexes based on accessing in stable order (think std::list)
  • Indexes based on random access in stable order (think std::vector)

基于键的索引也可以是唯一的(例如std::map),也可以是不唯一的(例如std::multimap).

The key-based indexes can also be either unique (like std::map), or non-unique (like std::multimap).

在定义容器时,将要具有的每个索引作为一个模板参数传递给boost::multi_index::indexed_by. (在上面的示例中,我添加了三个索引).

When defining the container, you pass each index you want to have as one template argument to boost::multi_index::indexed_by. (In our example above, I added three indexes).

对于不使用键的索引(稳定顺序和随机访问),不需要指定任何内容;您只是说我想要这样的索引."

For indexes which do not use a key (stable order & random access), nothing needs to be specified; you just say "I want such an index."

对于基于键的索引,还需要指定如何从数据中获取键.那就是关键提取器起作用的地方. (这是示例中boost::multi_index::member的三种用法).基本上,对于每个索引,您都提供了一种配方(或算法),用于从存储在容器中的数据派生密钥.当前可用的密钥提取器是:

For key-based indexes, you also need to specify how the key is obtained from the data. That's where key extractors come into play. (These are the three uses of boost::multi_index::member in the example). Basically, for each index, you provide a recipe (or algorithm) for deriving the key from the data stored in the container. Currently available key extractors are:

  • 使用元素本身:identity
  • 使用元素的数据成员:member
  • 使用元素的(恒定)成员函数:[const_]mem_fun
  • 使用全局函数:global_fun
  • 将多个密钥提取器组合为一个:composite_key
  • Use the element itself: identity
  • Use a data member of the element: member
  • Use a (constant) member function of the element: [const_]mem_fun
  • Use a global function: global_fun
  • Combine multiple key extractors into one: composite_key

请注意,键提取器可以透明地取消引用指针.也就是说,如果您的数据元素是指向类C的指针,则可以在类C上指定键提取器,并且取消引用将自动进行. (示例中也使用了此属性.)

Note that key extractors are able to dereference pointers transparently. That is, if your data element is a pointer to class C, you can specify key extractors over class C and the dereference will happen automagically. (This property is also used in the example).

通过这种方式定义带有索引的容器.要访问索引,请在容器上调用get成员函数模板.您可以在indexed_by的模板参数列表中按序号引用索引.对于更具可读性的操作,您可以为每个索引(或其中一些索引)引入标签.标记是任意类型(通常是带有适当名称的空结构),它允许您将该类型用作get的模板参数,而不是索引的序号. (在示例中也使用了此方法.)

This way a container with indexes is defined. To access an index, you call the get member function template on the container. You can refer to an index by its sequential number in the list of template arguments of indexed_by. For more readable manipulation, you can however introduce a tag for each index (or just some of them). A tag is an arbitrary type (usually an empty structure with a suitable name) which allows you to use that type as template argument for get instead of the index's sequential number. (This is also used in the example).

一旦从容器中检索到对索引的引用,就可以像索引所对应的数据结构(映射,哈希集,向量等)一样使用它.通过该索引所做的更改将影响整个容器.

Once you retrieve a reference to an index from the container, you can use it just like the data structure to which the index corresponds (map, hashset, vector, ...). Changes done through that index will affect the entire container.

这篇关于如何使用/创建boost :: multi_index?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆