对不起,我不能在标题中更具体。
假设我有一堂课Foo
class Foo {
public:
Foo() { m_bitset.reset(); }
void set_i(int i) {
m_bitset.set(1);
m_i = i;
}
void set_j(int j) {
m_bitset.set(2);
m_j = j;
}
bool i_set() { return m_bitset(1); }
bool j_set() { return m_bitset(2); }
void clear_i() { m_bitset.reset(1); }
void clear_j() { m_bitset.reset(2); }
int get_i() {
assert(i_set());
return m_i;
}
int get_j() {
assert(j_set());
return m_j;
}
private:
int m_i, m_j;
bitset<2> m_bitset;
};
现在我想将Foo放入multi_index。
typedef multi_index_container <
Foo,
indexed_by<
ordered_non_unique<BOOST_MULTI_INDEX_CONST_MEM_FUN( Foo, int, get_i)
>,
ordered_non_unique<BOOST_MULTI_INDEX_CONST_MEM_FUN( Foo, int, get_j)
>
>
> Foo_set;
我想弄清楚的是让我的multi_index对具有有效值i或j的Foo进行排序(或者在composite_key的情况下将两者都排序并传递其余部分。 所以我不希望下面的代码爆炸,我只想返回有效的i值的foos。
for (Foo_set::nth_index<1>::type::iterator it = foos.get<1>().begin(); it != foos.get<1>().end(); ++it)
cout << *it;
答案 0 :(得分:1)
通过浏览boost multi_index库文档,我会说这个库无法实现你想要的东西。看看它的rationale,它似乎仅用于索引可在所有“维度”上完全索引的元素。 (如果存在允许“稀疏”索引维度的任何黑客攻击,您可以尝试询问提升用户邮件列表。)
无论如何 - 根据问题的确切性质,您可以通过使用boost :: optional作为索引类型来解决它。 (虽然我甚至不确定是否可以通过boost :: optional进行索引。)
答案 1 :(得分:1)
在assert()
和get_i()
函数中使用get_j()
会导致硬件程序在multi_index要求索引i
或j
值时停止。 / p>
听起来你想要Null Object Pattern行为。即m_i
和m_j
是数据类型,它们使用特殊值来表示它们未被设置(如果它们是指针,NULL
指针将用于此目的)。然后,您的多索引可以索引这些值,将所有null
值集中在一起。
访问数据时,您可以使用boost::range过滤掉空值:
// Predicate for null testing
struct is_not_null {
bool operator()(const Foo& f) { return f.get_i() != NULL && f.get_j() != NULL; }
};
Foo_set::nth_index<1>::type& idx = foos.get<1>();
BOOST_FOREACH(const Foo& f, idx | filtered(is_not_null())) {
;// do something with the non-null Foo's
}
如果您不想污染变量的值空间(即没有可存储的有意义的空值),您还可以考虑转换m_i
和m_j
成员进入boost::optional的。通过更多仿函数包装,您可以创建<bool, int>
的综合索引,这将允许您分别访问设置或取消设置Foo
。您可以进一步撰写索引,将i
和j
与看起来像<bool, bool, int, int>
的复合索引合并。