如果我有这样的对象:
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
,但我无法弄清楚如何使它在多索引容器的上下文中工作。
答案 0 :(得分:6)
您可以编写用户定义的密钥提取器,而不是提供用户定义的比较器:
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;
答案 1 :(得分:5)
我相信你需要创建一个带有两个Foo实例的谓词对象,它的operator()可以在两个实例上调用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>,
...
答案 2 :(得分:1)
尽管我喜欢使用lambdas做简单的事情,但这很快就会退化:)
在你的情况下,因为它有点复杂,我会依赖于自由函数或谓词比较器。
谓词具有更清晰地定义类型的优点,因此通常更容易实现它。
另外,为了便于阅读,我通常会输入我的索引,这给出了:
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;
谓词方法需要更多样板代码,但它允许将比较逻辑与索引定义很好地分开,索引定义本身与容器定义分开。
清晰的分离使得查看结构一目了然。