2010-11-18 11 views
6

mam przechowującą pęczek następującymZdobądź indeks liczbowy od doładowania multi-index iterator

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

w pojemniku Boost.MultiIndex, zdefiniowany jako

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; 

teraz mam dwa iteratory, jeden z index<by_title> i jeden z index<by_id>. Jaki jest najłatwiejszy sposób przekształcenia ich w indeksy w część o swobodnym dostępie do kontenera, bez dodawania elementu danych do struct Article?

Odpowiedz

6

Każdy indeks obsługuje generowanie iteratora według wartości za pomocą iterator_to. Jeśli masz już iterator do wartości docelowej w jednym indeksie, możesz użyć tego do konwersji na iterator w innym indeksie.

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

Dla konwersji do indeksu można prawdopodobnie wzorować w 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; 
    } 
+0

Tak więc 'iterator_to (* it)' powinien dać mi iterator dostępu losowego? I w jaki sposób mogę przekonwertować to na indeks numeryczny, ponieważ tego właśnie potrzebuję (aby zaindeksować w macierz)? –

+2

@larsman - sądząc po wnętrzach kodu random_indexed, warunkiem jest, że iteratory na takim indeksie są różne, tzn. 'iter - index.begin()' powinien działać. Zobacz edycję. –

6

iterator_to to stosunkowo nowa funkcja w Boost, (jest tam od 1,35). Dodaje trochę cukru składniowego podczas korzystania z domyślnego indeksu. W starszych wersjach funkcji Boost jedyną opcją jest funkcja project. Można użyć project w następujący sposób:

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

Tak, to też działa. Dam ci +1, gdy dostanę nowe głosy :) –

+0

+1 Jestem ciekawy @Kyrill - pod okładkami, zarówno ta jak i moja odpowiedź wydają się używać 'make_iterator' na wartości węzła. Jakiś powód, by preferować jedno lub drugie? –

+0

Możliwym tego powodem jest to, że ukrywa on dereferencje od użytkownika. Nie podoba mi się '<0>' bit, chociaż ... –

Powiązane problemy