我有一个这样的类(简化示例):
class A {
public:
typedef boost::shared_ptr<A> Ptr;
const std::string& getID() const;
const std::string& getLabel() const;
bool getFlag() const;
float getValue() const;
private:
...
};
我需要一个容器,该容器由 的唯一组合(id, label)
以及(label, flag, value)
. 我还需要它按标签的第二个索引排序,然后是标志,如果标志为真,则减少值,如果标志为假,则增加值。所以在创建密钥提取器之后,我正在做这样的事情:
typedef boost::multi_index::composite_key<
Ptr, extractor_id, extractor_label
> id_label_key;
typedef boost::multi_index::composite_key<
Ptr, extractor_label, extractor_flag, extractor_value
> label_flag_value_key;
...
typedef boost::multi_index_container<Ptr,
boost::multi_index::indexed_by<
boost::multi_index::ordered_unique<
boost::multi_index::tag<by_id_label
id_label_key
>,
boost::multi_index::ordered_unique<
boost::multi_index::tag<by_label_flag_value>,
label_flag_value_key,
Compare
>,
>
> Items;
typedef Items::index<by_label_flag_value>::type Items_by_label_flag_value;
其中比较定义为:
struct Compare {
bool operator() (const boost::multi_index::composite_key_result<label_flag_value_key>& k, const boost::tuple<float,bool>& q) const {
return compare(k.value->getLabel(), k.value->getFlag(), k.value->getValue(),
q.get<0>(), q.get<1>(), q.get<2>()
}
bool operator() (const boost::tuple<float,bool>& q, const boost::multi_index::composite_key_result<label_flag_value_key>& k) const {
return compare(q.get<0>(), q.get<1>(), q.get<2>(),
k.value->getLabel(), k.value->getFlag(), k.value->getValue(),
}
bool operator() (const boost::multi_index::composite_key_result<label_flag_value_key>& k1, const boost::multi_index::composite_key_result<label_flag_value_key>& k2) const {
return compare(k1.value->getLabel(), k1.value->getFlag(), k1.value->getValue(),
k2.value->getLabel(), k2.value->getFlag(), k2.value->getValue())
}
bool compare(const std::string& l1, bool f1, float v1, const std::string& l2, bool f2, float v2) const {
if (l1 != l2) return l1 < l2;
if (f1 != f2) return f1;
return f1 ? (v1 > v2) : (v1 < v2);
}
};
现在,我可以执行如下查询:
Items_by_label_flag_value::const_iterator it = items_by_label_flag_value.find(boost::make_tuple("A", true, 0.1));
但是,如果我尝试执行部分查询 - 例如,检索具有相同标签的所有项目 - 我的代码将无法编译:
std::pair<Items_by_label_flag_value::const_iterator, Items_by_label_flag_value::const_iterator> range = items_by_label_flag_value.equal_range(boost::make_tuple("A"));
我知道它为什么不编译:在比较器中我明确使用,.get<0>()
但部分搜索元组没有.get<1>()
和元素。我不知道如何创建正确的比较器。如果我尝试向它添加另外两个仅采用一个元素的元组的函数,那么编译器会抱怨调用中的歧义。.get<2>()
<1>
<2>
operator()
我也明白这composite_key_result
应该是一个不透明的对象,我不应该使用它的内部。
所以我的问题是如何创建所需的索引和正确的比较器?