2010-11-18 23 views
6

Ben bir demet depolamak ediyorumBoost çoklu dizin yineleyicisinden sayısal dizin alın

struct Article { 
    std::string title; 
    unsigned db_id;  // id field in MediaWiki database dump 
}; 

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; 

Şimdi iki yineleyicinızı, index<by_title> itibaren bir ve index<by_id> itibaren bir var olarak tanımlanan bir Boost.MultiIndex konteyner, aşağıdaki. Bir veri elemanı struct Article için eklemeden, kabın rasgele erişim parçası haline endeksler bu dönüştürmek için en kolay yolu nedir?

cevap

6

Her dizin, iterator_to kullanarak bir yineleyicinin üretimini değerlere göre destekler. Bir dizinde hedef değere sahip bir yineleyiciniz varsa, bunu başka bir dizinde bir yineleyiciye dönüştürmek için kullanabilirsiniz.

iterator  iterator_to(const value_type& x); 
const_iterator iterator_to(const value_type& x)const; 

endeksine dönüşüm için büyük olasılıkla random_access_index.hpp modeli takip edebilirsiniz:

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; 
    } 
+0

Yani 'iterator_to (* o)' Bana bir rasgele erişim yineleyici vermelidir: aşağıdaki gibi project kullanabilirsiniz? Ve bunu sayısal bir dizine nasıl dönüştürürüm, çünkü gerçekten ihtiyacım olan şey (matrisin içine indekslemek)? –

+2

@larsman - random_indexed kodunun içersine göre değerlendirildiğinde, gereksinim, böyle bir endeks üzerindeki yineleyicilerin farklılık gösterebilmesidir, yani. iter - index.begin() 'çalışması gerekir. Düzenleme konusuna bakın. –

6

iterator_to Boost nispeten yeni fonksiyondur (o 1,35 beri vardır). Varsayılan indeks ile kullanırken sözdizimi şeker biraz ekler. Boost'un eski sürümleri için project işlevi tek seçenektir.

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. 
+0

Evet, bu da işe yarıyor. Yeni oylar aldığımda size +1 vereceğim :) –

+0

+1 Ben merak ediyorum @Kyrill - kapakların altında, hem bu hem de benim cevabım düğüm değerinde make_iterator' kullanıyor görünüyor. Birini diğerini tercih etmek için herhangi bir sebep var mı? –

+0

Bunu tercih etmenin olası bir nedeni, kullanıcının dizinden kaldırılmasını gizlemesidir. <0> 'bit'i gerçekten istemiyorum ... –

İlgili konular