从Boost多索引迭代器获取数字索引

Fre*_*Foo 6 c++ containers boost multi-index boost-multi-index

我存储了一堆以下内容

struct Article {
    std::string title;
    unsigned db_id;     // id field in MediaWiki database dump
};
Run Code Online (Sandbox Code Playgroud)

在Boost.MultiIndex容器中,定义为

typedef boost::multi_index_container<
    Article,
    indexed_by<
        random_access<>,
        hashed_unique<tag<by_db_id>,
                      member<Article, unsigned, &Article::db_id> >,
        hashed_unique<tag<by_title>,
                      member<Article, std::string, &Article::title> >
    >
> ArticleSet;
Run Code Online (Sandbox Code Playgroud)

现在我有两个迭代器,一个来自index<by_title>,一个来自index<by_id>.将这些索引转换为容器的随机访问部分的最简单方法是什么,而不添加数据成员struct Article

Ste*_*end 6

每个索引都支持使用iterator_to按值生成迭代.如果在一个索引中已经有一个目标值的迭代器,则可以使用它转换为另一个索引中的迭代器.

iterator       iterator_to(const value_type& x);
const_iterator iterator_to(const value_type& x)const;
Run Code Online (Sandbox Code Playgroud)

要转换为索引,您可以遵循以下模型random_access_index.hpp:

  iterator erase(iterator first,iterator last)
  {
    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
    BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,*this);
    BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,*this);
    BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
    BOOST_MULTI_INDEX_RND_INDEX_CHECK_INVARIANT;
    difference_type n=last-first;
    relocate(end(),first,last);
    while(n--)pop_back();
    return last;
  }
Run Code Online (Sandbox Code Playgroud)

  • @larsman - 根据random_indexed代码的内部判断,要求是这样的索引上的迭代器是可区分的,即.`iter - index.begin()`应该工作.见编辑. (2认同)

Kir*_*sky 6

iterator_to在Boost中它是一个相对较新的函数(从1.35开始就存在).使用默认索引时,它会添加一些语法糖.对于旧版本的Boost,该功能project是唯一的选择.您可以使用project如下:

ArticleSet x;
// consider we've found something using `by_db_id` index
ArticleSet::index_const_iterator<by_db_id>::type it = 
  x.get<by_db_id>().find( SOME_ID );

// convert to default index ( `random_access<>` )
ArticleSet::const_iterator it1 = x.project<0>( it );
// iterator_to looks like:
ArticleSet::const_iterator it11 = x.iterator_to( *it );

// convert to index tagged with `by_title` tag
ArticleSet::index_const_iterator<by_title>::type it2 = x.project<by_title>( it );
// iterator_to doen't look better in this case:
ArticleSet::index_const_iterator<by_title>::type it2 = x.get<by_title>().iterator_to( *it );

// etc.
Run Code Online (Sandbox Code Playgroud)