Domanda

Se ho un contenitore (vector, list, ecc.) in cui ogni elemento è un std::pair, esiste un modo semplice per scorrere su ogni elemento di ogni coppia?

vale a dire.

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));

e quindi essere in grado di scorrere il valore: 1,3,2,3,4,2,5,2,1,5?

Allo stesso modo, quale tipo di funzione / funzione mi restituirebbe un contenitore (dello stesso tipo) con un elenco piatto degli elementi di coppia come sopra?

È stato utile?

Soluzione

Per appiattire il tuo contenitore di coppie in un secondo contenitore puoi anche semplicemente scrivere il tuo inseritore:

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));

Altri suggerimenti

Per la prima volta, devi creare la tua classe iteratore, che accoppia un flag che indica la posizione all'interno della coppia con un container<pair> iteratore

Per il secondo, è più semplice, anche se per essere il più generale possibile (contenitore dello stesso tipo) è necessario un template typedef . Ecco solo per il vettore:

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

Ecco come falsificare un modello typedef:

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);

Il seguente codice stamperà tutti i valori come richiesto:

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

Preferirei questo modo semplice rispetto alla creazione di un iteratore personalizzato.

Non esiste un modo semplice per eseguire l'iterazione desiderata, ma potresti dare un'occhiata alla libreria boost :: iterator_adaptor o implementare il tuo iteratore per farlo (non dovrebbe essere troppo complesso). Quindi, sulla seconda domanda, puoi usare std :: copy con il tuo nuovo adattatore iteratore.

No, non esiste davvero nulla del genere per std::pair. In alternativa, potresti prendere in considerazione l'utilizzo di una tupla boost. Una tupla è un po 'come una versione estesa di <=> che consente un numero arbitrario di elementi (fino a un certo limite, ma normalmente almeno 10), e dà accesso agli elementi anche qualcosa come un vettore / array (cioè tu può accedere agli elementi tramite nome o indice).

TR1 include anche std :: tr1 :: tuple, che è un sottoinsieme della tupla di Boost, ma se la memoria serve, include comunque la funzionalità nome / indice che stai chiedendo.

Modifica: si noti che in entrambi i casi, la notazione dell'indice richiede una costante tempo di compilazione per l'indice, quindi non è possibile scrivere un ciclo (runtime) per scorrere gli elementi in una tupla - ma puoi fare il lavoro con un po 'di metaprogrammazione. Potenziare la fusione include parecchio per supportare ciò di cui avresti bisogno (per una strana coincidenza, la tupla fa parte della libreria di fusione).

Ad un certo punto devi usare primo e secondo , anche se crei la tua classe iteratore. Non penso che ci sia una via d'uscita (almeno, in modo portatile).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top