使用基于嵌套值的索引增强多索引容器

发布于 2024-08-08 22:54:16 字数 809 浏览 9 评论 0原文

如果我有一个这样的对象:

struct Bar {
    std::string const& property();
};

我可以为它创建一个多索引容器,如下所示:

struct tag_prop {};
typedef boost::multi_index_container<
    Bar,
    boost::multi_index::indexed_by<
        boost::multi_index::ordered_non_unique<
            boost::multi_index::tag<tag_prop>,
            boost::multi_index::const_mem_fun<
                Bar, const std::string&, &Bar::property
            >
        >
    >
    , ... other indexes
> BarContainer;

但是如果我有一个这样的类:

struct Foo {
   Bar const& bar();
};

如何在 .bar().property() 用于 Foo 对象的容器?

通常我会嵌套对 boost::bind 的调用,但我不知道如何使其在多索引容器的上下文中工作。

If I have an object like this:

struct Bar {
    std::string const& property();
};

I can create a multi-index container for it like this:

struct tag_prop {};
typedef boost::multi_index_container<
    Bar,
    boost::multi_index::indexed_by<
        boost::multi_index::ordered_non_unique<
            boost::multi_index::tag<tag_prop>,
            boost::multi_index::const_mem_fun<
                Bar, const std::string&, &Bar::property
            >
        >
    >
    , ... other indexes
> BarContainer;

But if I have a class like this:

struct Foo {
   Bar const& bar();
};

How can I construct an index on .bar().property() for a container of Foo objects?

Normally I would nest calls to boost::bind, but I can't figure out how to make it work in the context of a multi-index container.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

内心激荡 2024-08-15 22:54:16

您可以编写用户定义的密钥提取器,而不是提供用户定义的比较器:

struct FooBarPropertyExtractor
{
  typedef std::string result_type;
  const result_type& oeprator()(const Foo& f)
  {
    return f.bar().property();
  }
};

...

typedef boost::multi_index_container<
        Bar,
        boost::multi_index::indexed_by<
                boost::multi_index::ordered_non_unique<
                        boost::multi_index::tag<tag_prop>,
                        FooBarPropertyExtractor
                >
        >
        , ... other indexes
> FooContainer;

请参阅Boost.MultiIndex 密钥提取器的高级功能

Rather than providing a user-defined comparator, you can write a user-defined key extractor:

struct FooBarPropertyExtractor
{
  typedef std::string result_type;
  const result_type& oeprator()(const Foo& f)
  {
    return f.bar().property();
  }
};

...

typedef boost::multi_index_container<
        Bar,
        boost::multi_index::indexed_by<
                boost::multi_index::ordered_non_unique<
                        boost::multi_index::tag<tag_prop>,
                        FooBarPropertyExtractor
                >
        >
        , ... other indexes
> FooContainer;

See Advanced features of Boost.MultiIndex key extractors

别再吹冷风 2024-08-15 22:54:16

我相信您需要创建一个谓词对象,该对象采用 Foo 的两个实例,并且其运算符()可以在两个实例上调用 Foo::bar() 。

类似于

struct MyPredicate
{

    bool operator() (const Foo& obj1, const Foo& obj2) const
    {
        // fill in here
    }
};

然后使用

...
boost::multi_index::ordered_unique<boost::multi_index::tag<tag_prop>, 
    boost::multi_index::identity<Foo>, MyPredicate>,
...

查看 MultiIndex 有序索引参考

I believe you need to create a predicate object that takes two instances of Foo and its operator() can call Foo::bar() on both instances.

Something like

struct MyPredicate
{

    bool operator() (const Foo& obj1, const Foo& obj2) const
    {
        // fill in here
    }
};

and then use

...
boost::multi_index::ordered_unique<boost::multi_index::tag<tag_prop>, 
    boost::multi_index::identity<Foo>, MyPredicate>,
...

Check out MultiIndex Ordered indices reference

萌酱 2024-08-15 22:54:16

尽管我喜欢使用 lambda 来做简单的事情,但这很快就会退化:)

在你的情况下,因为它有点复杂,我会依赖自由函数或谓词比较器。

谓词的优点是可以更清晰地定义类型,因此通常更容易实际引入它。

此外,为了可读性,我通常对索引进行 typedef,这给出了:

namespace mi = boost::multi_index;

struct FooComparator
{
  bool operator()(Foo const& lhs, Foo const& rhs) const
  {
    return lhs.bar().property() < rhs.bar().property();
  }
};

typedef mi::ordered_unique <
          mi::tag<tag_prop>,
          mi::identity<Foo>,
          FooComparator
        > foo_bar_index_t;

typedef boost::multi_index_container <
          Foo,
          mi::indexed_by < 
            foo_bar_index_t,
            // ... other indexes
          >
        > foo_container_t;

谓词方法需要更多样板代码,但它允许很好地分离来自索引定义的比较逻辑,索引本身与容器定义分离。

清晰的分隔使得结构一目了然。

As much as I like using lambdas to do simple things, this can quickly degenerate :)

In your case, since it's a bit more complicated, I would rely either on a free function or a predicate comparator.

The predicate has the advantage of defining types more clearly so it's usually easier to actually bring it in.

Also, for readability's sake, I usually typedef my indexes, which gives:

namespace mi = boost::multi_index;

struct FooComparator
{
  bool operator()(Foo const& lhs, Foo const& rhs) const
  {
    return lhs.bar().property() < rhs.bar().property();
  }
};

typedef mi::ordered_unique <
          mi::tag<tag_prop>,
          mi::identity<Foo>,
          FooComparator
        > foo_bar_index_t;

typedef boost::multi_index_container <
          Foo,
          mi::indexed_by < 
            foo_bar_index_t,
            // ... other indexes
          >
        > foo_container_t;

The predicate approach requires more boilerplate code, but it allows to nicely separate the comparison logic from the index definition, which is itself separated from the container definition.

Clear separation makes it easier to view the structure at a glance.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文