Ich muss zugeben, dass mir Potatoswatters Lösung ziemlich gut gefällt... ziemlich.
Wie er demonstriert hat, handelt es sich hier nicht um ein Algorithmusproblem, sondern um ein Iterationsproblem. Allerdings passt seine Lösung nicht ganz, weil das Testen des Ende
der Iteration sehr schwierig ist: Es erfordert viel Sorgfalt bei der Vorbereitung der Container und der Erstellung der Iteratoren, um undefiniertes Verhalten zu vermeiden.
Ich denke, das Problem könnte viel besser ausgedrückt werden, wenn man ein Konzept verwendet, das ziemlich ähnlich zu Iteratoren ist: Ansichten.
Eine Ansicht ist eine Adapter-Schnittstelle über einen oder mehrere Container. Sie enthält tatsächlich nichts (das ist der wichtige Teil). Sie stellt jedoch eine Schnittstelle bereit, die der eines Containers ähnelt, sodass Sie mit den üblichen Idiomen coden können.
Das Schöne an Ansichten ist, dass man sie oft kombinieren kann.
Zum Beispiel eine sehr einfache Ansicht:
/// Erlaubt nur, einen Bereich des Containers zu sehen:
/// std::vector v(40, 3); // { 3, 3, 3, ... }
/// auto rv = make_range_view(v, 4, 5);
/// rv zeigt die Elemente im Bereich [4,9)
/// Im Debug-Modus wird sichergestellt, dass der Bereich ausreichend groß ist.
template
class range_view
{
};
Für Ihre Frage sollten Sie eher eine interleave_view
erstellen:
/// Ermöglicht das Einflechten von Elementen aus 2 Containern jeweils in ihrem eigenen Tempo
/// std::vector v(40, 3);
/// std::set s = /**/;
///
/// auto iv = make_interleave_view(v, 3, s, 1);
/// Nimmt 3 Elemente aus v, dann 1 aus s, dann 3 aus v, usw...
template
class interleave_view
{
};
Hier wird das Problem des Enditerators irgendwie gemildert, weil wir beide Container kennen und somit in der Lage sind, die Iteratoren selbst zu erstellen und sicherzustellen, dass wir die richtigen Parameter übergeben.
Natürlich kann es etwas mühsamer werden, wenn die Container kein effizientes "size"-Element bieten (list
bietet das nicht, es ist O(n)).
Das allgemeine Prinzip jedoch ist, dass eine Ansicht Ihnen mehr Kontrolle gibt (und ermöglicht mehr Überprüfungen) und sicherer zu verwenden ist, weil Sie genau die Erstellung der Iteratoren kontrollieren.
Beachten Sie, dass in C++0x das interleave_view
typischerweise eine unbegrenzte Anzahl von Sequenzen aufnehmen würde.