Boost Multi_Index Question

我是研究僧i 提交于 2020-01-02 07:28:50

问题


Sorry I can't be more specific in the title.

Let's say I have a class 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;
};

And now I want to put Foo's into a 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;

What I'm trying to figure out is a way to have my multi_index sort the Foo's that have valid values of i or j (or both in the case of a composite_key and pass over the rest. So I don't want the code below to blow up, I just want to only return foos that have valid values for i.

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

回答1:


From skimming over the boost multi_index library docs I'd say what you want is not possible with this library. Looking at its rationale it appears that it is only made for indexing elements that are fully indexable over all "dimensions". (You might try asking on the boost users mailing list if there are any hacks to allow "sparse" index dimensions.)

Anyways - depending on the exact nature of your problem you might be able to work around it by using a boost::optional as indexing type. (Although I'm not even sure it's possible to index by boost::optional.)




回答2:


Having assert() in your get_i() and get_j() functions will cause a hard program stop when multi_index asks for the i or j values for indexing.

It sounds like you want Null Object Pattern behaviour. I.e. m_i and m_j are data-types that take special values to indicate they are not set (if they were pointers, the NULL pointer would serve this purpose). Then your multi-index could index on those values, lumping all the null values together.

When accessing the data, you can use boost::range to filter out the null values:

// 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
}

If you don't want to pollute the value-space of your variables (i.e. there is no meaningful null value that can be stored), you could also look into converting your m_i and m_j members into boost::optional's. With a bit more functor wrapping, you could create a composite index of <bool, int>, which would allow you to access set or unset Foo's separately. You can further compose the index to combine i and j with a composite index that looks like <bool, bool, int, int>.



来源:https://stackoverflow.com/questions/3485922/boost-multi-index-question

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!