获取 boost::multi_index 容器元素的排名

get the rank of an element of a boost::multi_index container

下面的代码显示了一个 multi_index 容器,它按顺序和顺序索引。

在我的用例中,元素将主要通过索引搜索,如果存在,则获取下一个元素(按顺序)。

我的问题是,如何获得获得的下一个元素的排名(按顺序)?

#include <iostream>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/ranked_index.hpp>
#include <boost/multi_index/identity.hpp>

using namespace boost::multi_index;

typedef multi_index_container <
    int
  , indexed_by<
        sequenced<>
      , ordered_non_unique<identity<int>>
      , ranked_non_unique<identity<int>>
    >
> Ints;

int main() {
    Ints ints;

    auto & sequence=ints.get<0>();
    auto & order=ints.get<1>();

    sequence.push_back(2);
    sequence.push_back(-1);
    sequence.push_back(5);
    sequence.push_back(6);

    auto it = order.find(2);
    if (it!=order.end()) {
        std::cout
            << "next to "
            << *it
            << " by sequence is "
            << *(++(ints.project<0>(it)))
            << std::endl
        ;
        std::cout
            << "next to "
            << *it
            << " by order is "
            << *(++(ints.project<1>(it))) //++it is good too
            << std::endl
        ;
        std::cout
            << "rank of next by sequence is "
            // << ??? ints.rank<???>(???)
            << std::endl
        ;
        std::cout
            << "rank of next by order is "
            // << ??? ints.rank<???>(???)
            << std::endl
        ;
    }
}

假设您想要某种 "index into" 或 "offset from begin" 的顺序索引:

if (it!=order.end()) {
    auto rank_of = [&](auto it) {
        return std::distance(sequence.begin(), ints.project<0>(it));
    };

    auto seq_next = std::next(seq_it);
    auto ord_next = std::next(it);

    if (seq_next!=sequence.end())
    {
        std::cout << "next to                     " << *it << " by sequence is " << *seq_next << std::endl;
        std::cout << "rank of next by sequence is " << rank_of(seq_next) << std::endl;
    }

    if (ord_next!=order.end())
    {
        std::cout << "next to                     " << *it << " by order is " << *ord_next << std::endl ;
        std::cout << "rank of next by order is    " << rank_of(ord_next) << std::endl;
    }
}

如果没有多态 lambda,你应该写出来

@sehe 的回答完全有效,但在线性时间内运行。如果您想要更好的性能,请考虑将索引 #0 定义为 random_access 并将 #1 定义为 ranked_non_unique (索引 #2 是多余的):

typedef multi_index_container <
    int
  , indexed_by<
        random_access<>
      , ranked_non_unique<identity<int>>
    >
> Ints;

这样你就可以写:

std::cout
    << "rank of next by sequence is "
    << ints.project<0>(it)-sequence.begin()+1 // O(1)
    << std::endl
;
std::cout
    << "rank of next by order is "
    << order.rank(it)+1 // O(log n)
    << std::endl
;