Question

Si j’ai un conteneur (vector, list, etc.) où chaque élément est un std::pair, existe-t-il un moyen simple d’itérer chaque élément de chaque paire?

i.e.

std::vector<std::pair<int,int> > a;
a.push_back(std::pair(1,3));
a.push_back(std::pair(2,3));
a.push_back(std::pair(4,2));
a.push_back(std::pair(5,2));
a.push_back(std::pair(1,5));

et pouvoir ensuite parcourir la valeur: 1,3,2,3,4,2,5,2,1,5?

De même, quel type de foncteur / fonction me retournerait un conteneur (du même type) avec une liste à plat des éléments de la paire comme ci-dessus?

Était-ce utile?

La solution

Pour aplatir votre conteneur de paires dans un second conteneur, vous pouvez également écrire votre propre insertion:

template<class C>
struct Inserter {
    std::back_insert_iterator<C> in;
    Inserter(C& c) : in(c) {}
    void operator()(const std::pair<typename C::value_type, typename C::value_type>& p)
    {
        *in++ = p.first;
    *in++ = p.second;
    }
};

template<class C>
Inserter<C> make_inserter(C& c)
{ 
    return Inserter<C>(c); 
}

// usage example:
std::list<int> l;
std::for_each(a.begin(), a.end(), make_inserter(l));

Autres conseils

Pour votre première création, vous devez créer votre propre classe d'itérateurs, qui associe un drapeau indiquant la position dans la paire à un container<pair> itérateur

.

Pour le second, c'est plus facile, bien que pour être aussi général que vous le souhaitez (conteneur du même type), vous avez besoin d'un template typedef . Voici juste pour le vecteur:

template <class V>
std::vector<V> flatten_pairs(std::vector<std::pair<V,V> > const& a) {
  typedef std::vector<std::pair<V,V> > A;
  std::vector<V> ret;
  for (typename A::const_iterator i=a.begin(),e=a.end();i!=e;++i) {
    ret.push_back(i->first);
    ret.push_back(i->second);
  }
  return ret;
}

Voici comment vous simulez un gabarit:

template <class C>
struct same_container;

template <class V>
struct same_container<std::vector<V> > {
  template <class W> struct rebind { typedef std::vector<W> type; };
};

template <class V>
struct same_list<std::list<V> > {
  template <class W> struct rebind { typedef std::list<W> type; };
};

template <class C>
typename same_container<C>::rebind<typename C::value_type::first_type>::type
flatten_pairs(C const& a);

Le code suivant affichera toutes les valeurs requises:

for ( size_t x = 0; x < a.size(); ++x ) {
    cout << a[x].first << "," << a[x].second << ",";
}

Je préférerais cette méthode simple à la création d'un itérateur personnalisé.

Il n’existe pas de moyen simple de réaliser l’itération souhaitée, mais vous voudrez peut-être jeter un coup d’œil à la bibliothèque boost :: iterator_adaptor ou utiliser votre propre itérateur pour le faire (cela ne devrait pas être trop complexe). Ensuite, sur la deuxième question, vous pouvez utiliser std :: copy avec votre nouvel adaptateur itérateur.

Non, il n’ya vraiment pas de chose pareille pour std::pair. Vous voudrez peut-être envisager d'utiliser un booster de booster. Un tuple est un peu comme une version développée de <=> qui autorise un nombre arbitraire d’éléments (jusqu’à une certaine limite, mais normalement au moins 10), et donne également accès aux éléments comme un vecteur / tableau accéder aux éléments par nom ou par index).

TR1 inclut également std :: tr1 :: tuple, qui est un sous-ensemble du tuple de Boost, mais si la mémoire est bonne, il inclut toujours la fonctionnalité nom / index que vous demandez.

Modifier: notez que dans les deux cas, la notation d'index requiert une constante au moment de la compilation pour l'index. Vous ne pouvez donc pas écrire de boucle (d'exécution) pour parcourir les éléments dans un tuple - mais vous pouvez faire le travail avec un peu de métaprogrammation. Boost Fusion inclut un peu pour supporter ce dont vous auriez besoin (par une étrange coïncidence, le tuple fait partie de la bibliothèque de fusion).

À un moment donné, vous devez utiliser premier et deuxième , même si vous créez votre propre classe itérateur. Je ne pense pas qu'il y ait un moyen de s'en sortir (du moins, de manière portable).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top