【问题标题】:Boost Multi_Index QuestionBoost Multi_Index 问题
【发布时间】:2011-03-29 23:50:10
【问题描述】:

抱歉,我无法在标题中更具体。

假设我有一个班级 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 进行排序的方法(或者在复合键的情况下两者都通过其余的。 所以我不希望下面的代码爆炸,我只想返回对 i 具有有效值的 foos。

for (Foo_set::nth_index<1>::type::iterator it = foos.get<1>().begin(); it != foos.get<1>().end(); ++it)
    cout << *it;

【问题讨论】:

    标签: c++ boost multi-index


    【解决方案1】:

    通过浏览 boost multi_index 库文档,我想说你想要的东西是这个库不可能实现的。查看它的rationale,它似乎只用于索引在所有“维度”上完全可索引的元素。 (您可以尝试在 boost 用户邮件列表中询问是否有任何黑客允许“稀疏”索引维度。)

    无论如何 - 根据您的问题的确切性质,您可以通过使用 boost::optional 作为索引类型来解决它。 (虽然我什至不确定是否可以通过 boost::optional 进行索引。)

    【讨论】:

    • 是的,应该可以通过boost::optional索引。
    【解决方案2】:

    当 multi_index 请求 ij 索引值时,在 get_i()get_j() 函数中包含 assert() 会导致程序硬停止。

    听起来你想要空对象模式行为。 IE。 m_im_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_im_j 成员转换为 @987654322 @的。通过更多的函子包装,您可以创建&lt;bool, int&gt; 的复合索引,这将允许您分别访问设置或取消设置Foo。您可以进一步组合索引以将ij 与看起来像&lt;bool, bool, int, int&gt; 的组合索引组合起来。

    【讨论】:

      猜你喜欢
      • 2017-01-27
      • 1970-01-01
      • 2016-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多