2010-11-18 22 views
6

Je stocker un tas des éléments suivantsGet index numérique de multi-index Boost iterator

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

dans un récipient de Boost.MultiIndex, défini comme

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; 

Maintenant, j'ai deux itérateurs, un de index<by_title> et un de index<by_id>. Quel est le moyen le plus simple de les transformer en index dans la partie accès aléatoire du conteneur, sans ajouter un membre de données à struct Article?

Répondre

6

Chaque index prend en charge la génération d'un itérateur par valeur en utilisant iterator_to. Si vous avez déjà un itérateur à la valeur cible dans un index, vous pouvez l'utiliser pour convertir un itérateur dans un autre index.

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

Pour la conversion à l'index vous pouvez probablement suivre le modèle 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

donc 'iterator_to (* il)' devrait me donner un iterator accès aléatoire? Et comment puis-je convertir cela en un index numérique, parce que c'est ce dont j'ai vraiment besoin (indexer dans une matrice)? –

+2

@larsman - à en juger par les règles internes du code random_indexed, l'exigence est que les itérateurs sur un tel index soient différentiables, c'est-à-dire. 'iter - index.begin()' devrait fonctionner. Voir éditer. –

6

iterator_to est une fonction relativement nouvelle dans Boost (il est là depuis 1.35). Il ajoute un peu de la syntaxe du sucre lors de l'utilisation avec l'index par défaut. Pour les anciennes versions de Boost, la fonction project est le seul choix. Vous pouvez utiliser project comme suit:

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

Oui, ça marche aussi. Je vais vous donner un +1 quand j'aurai de nouveaux votes :) –

+0

+1 Je suis curieux @Kyrill - sous les couvertures, ceci et ma réponse semblent utiliser 'make_iterator' sur la valeur du noeud. Une raison de préférer l'un ou l'autre? –

+0

Une raison possible de préférer ceci est qu'il cache le déréférencement de l'utilisateur. Je n'aime pas vraiment '' <0> 'peu, cependant ... –