Повышение Multi_Index Вопрос - PullRequest
       32

Повышение Multi_Index Вопрос

3 голосов
/ 15 августа 2010

Извините, я не могу быть более конкретным в названии.

Допустим, у меня есть класс 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 отсортировать Foo, которые имеют допустимые значения i или j (или оба в случае составного_ключа, и передать остальные. Так что я не хочу, чтобы код ниже взорвался, я просто хочу возвращать только те foos, которые имеют допустимые значения для i.

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

Ответы [ 2 ]

1 голос
/ 10 февраля 2011

Наличие assert() в функциях get_i() и get_j() приведет к жесткой остановке программы, когда multi_index запрашивает значения i или j для индексации.

Звучит так, как вы хотитеНулевое поведение объекта 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 :: необязательно .Немного расширив функтор, вы можете создать составной индекс <bool, int>, который позволит вам обращаться к установленным или неустановленным Foo отдельно.Вы можете дополнительно составить индекс, чтобы объединить i и j с составным индексом, который выглядит как <bool, bool, int, int>.

1 голос
/ 06 сентября 2010

Из-за работы с документами над библиотеками boost multi_index я бы сказал, что то, что вы хотите, невозможно с этой библиотекой. Глядя на его обоснование , кажется, что он сделан только для индексации элементов, которые полностью индексируются по всем «измерениям». (Вы можете попробовать спросить в списке рассылки продвинутых пользователей, есть ли какие-нибудь хаки, позволяющие «разреженные» измерения индекса.)

В любом случае - в зависимости от точного характера вашей проблемы, вы можете обойти ее, используя boost :: option в качестве типа индексации. (Хотя я даже не уверен, что это можно проиндексировать с помощью Boost :: Option.)

...