Devo ammettere che mi piace molto la soluzione Potatoswatter ... abbastanza.
Come ha dimostrato, questo non è un problema di algoritmo, ma di iterazione. Tuttavia la sua soluzione non si adatta perfettamente alla fattura perché il test per l'end
dell'iterazione è molto difficile: richiede molta cura nella preparazione dei contenitori e nella creazione degli iteratori per evitare comportamenti indefiniti.
Penso che il problema potrebbe essere espresso molto meglio utilizzando un concetto che è abbastanza simile agli iteratori: viste.
Una vista è un'interfaccia dell'adattatore su uno o più contenitori. In realtà non contiene nulla (questa è la parte importante). Tuttavia espone un'interfaccia simile a quella di un contenitore in modo da poter codificare con i soliti idiomi.
Le cose belle dei panorami, è che puoi comporle spesso.
Per esempio, uno molto semplice vista:
/// Only allow to see a range of the container:
/// std::vector<int> v(40, 3); // { 3, 3, 3, ... }
/// auto rv = make_range_view(v, 4, 5);
/// rv exposes the elements in the range [4,9)
/// in debug mode, asserts that the range is sufficiently large
template <typename Container>
class range_view
{
};
Per la vostra domanda, si preferisce creare un interleave_view
:
/// Allow to interleave elements of 2 containers each at its own pace
/// std::vector<int> v(40, 3);
/// std::set<int> s = /**/;
///
/// auto iv = make_interleave_view(v, 3, s, 1);
/// Takes 3 elements from v, then 1 from s, then 3 from v, etc...
template <typename C1, typename C2>
class interleave_view
{
};
Qui la questione del iteratore finale è in qualche modo alleviato perché sappiamo entrambi i contenitori e quindi siamo in grado di creare noi stessi gli iteratori, assicurandoci di passare i parametri corretti.
Naturalmente può diventare un po 'più noioso se i contenitori non offrono un membro efficiente "dimensione" (list
no, è O (n)).
Il principio generale, tuttavia, è che una vista offre maggiore controllo (e consente un numero maggiore di controlli) ed è più sicuro da utilizzare perché si controlla con precisione la creazione degli iteratori.
Si noti che in C++ 0x lo interleave_view
generalmente corrisponde a un numero illimitato di sequenze.
Cosa succede alla fine di c? Vuoi averlo 4 4 8 .... 8 8 8 8 o semplicemente interrompere la fusione aIt è a.end() come nell'esempio? – dyp
Quindi, cosa succede se il vettore di input non ha abbastanza elementi? – AnT
L'STL ha già una convenzione per questo - cosa fa 'std :: transform' quando una sequenza di input non ha abbastanza elementi? – MSalters