Implementierung eines Generators in C ++ 0x

8

Das Python-Schlüsselwort yield war für mich eine großartige konzeptionelle Abstraktion, die es mir ermöglichte, die wichtigen Teile eines Algorithmus in eine für Menschen lesbare Form zu bringen. Wir haben bereits besprochen:

Python-Generatoren in verschiedenen Sprachen

wo eine Antwort für eine Windows-only-Bibliothek in C ++ gegeben wurde. Außerdem habe ich ein anderes Beispiel gefunden, das eine funkige Makroexpansion in der Frage verwendet:

Generatoren in C ++ - ungültige Verwendung des nicht statischen Datenelements

Der Vorteil meines Informatikwissens sagt mir, dass eine Yield-Funktion etwas hat mit Co-Routinen und Monaden zu tun, aber ich bin nicht ganz, wie das in das passt, was C ++ oder C ++ 0x erreichen kann.

Es scheint, dass in C ++ yeild ohne die Verwendung einer Makroexpansion oder einer Nur-Windows-Faser (thread) nicht implementiert werden kann. Ist das wahr? Ändert sich die Frage mit den zusätzlichen Sprachfunktionen von C ++ 0x?

    
Hooked 16.11.2011, 15:04
quelle

3 Antworten

4

Sie können yield python-Mechanismus C ++ Iteratoren zuordnen.

Siehe Boost-Funktion Input Iterator und das Beispiel:

  

Der Funktionseingabe-Iterator ermöglicht das Erstellen von Iteratoren, die ein Nullfunktionsobjekt und ein Zustandsobjekt kapseln, die die Anzahl der Wiederholungen des Iterators verfolgen. Ein Funktionseingabe-Iterator modelliert das InputIterator-Konzept und ist nützlich zum Erstellen von beschränkten Eingabe-Iteratoren.

     

Wie der Generator-Iterator nimmt der Funktionseingabe-Iterator eine Funktion an, die das Generator-Konzept modelliert (was im Grunde ein Null- oder 0-Aritätsfunktionsobjekt ist). Jedes Inkrement der Funktion Function Input Iterator ruft die Generatorfunktion auf und speichert den Wert im Iterator. Wenn der Iterator dereferenziert wird, wird der gespeicherte Wert zurückgegeben.

    
Maxim Egorushkin 16.11.2011, 16:19
quelle
3

yield ist im Grunde eine Möglichkeit, eine eingeschränkte Form von Koroutinen zu implementieren.

Wenn Sie zu stark genug wollen, können Sie (wie in "people have") relativ vollständige Korotinen in C mit setjmp und longjmp implementieren. In C ++ können Sie wahrscheinlich dasselbe tun, obwohl ich mir nicht ganz sicher bin. Das Problem mit C ++ besteht darin, zu entscheiden, welche Datentypen wann ausgeführt werden sollen. Ich denke, die Antwort ist, dass die Dtors nicht von der Coroutinenutzung betroffen sein sollten, aber ich habe nicht viel darüber nachgedacht. Angenommen, das ist korrekt, dann sollte ungefähr derselbe Code für C ++ wie für C funktionieren.

C ++ 0x fügt vollständige Unterstützung für Threads und ähnliches hinzu. Obwohl es ungeschickt sein kann und / oder den Overhead erhöhen kann, kann man so gut wie alles, was man mit Fasern tun kann, auch mit Fäden machen. Als solches würde es das Idiom ein wenig direkter unterstützen, so dass die Implementierung viel einfacher wäre.

    
Jerry Coffin 16.11.2011 15:14
quelle
1

Hmm Ich habe nie selbst Generatoren benutzt, aber von dem, was ich verstehe, wollen Sie eine Funktion, die einen Iterator zurückgibt, der den Inkrement-Operator ++ implementiert. Pseudocode:

%Vor%

Sie müssen den Iterator vom Zeiger zur Funktion f konstruieren und Sie können alle Argumente mit f an std::bind übergeben.

Nun müssen Sie bei jeder Iteration tatsächlich f aufrufen und die Funktion yield muss einige Stapelmanipulationen durchführen, um den aktuellen Stapel zu speichern, den ausgegebenen Wert zurückzugeben und den Stapel wiederherzustellen, wenn die Funktion erneut aufgerufen wird. Sie müssen den Stapel nur bis zu dem Punkt speichern, an dem f aufgerufen wird (es ist kein ganzer Stapel erforderlich), aber dies könnte schwierig zu implementieren sein. Wahrscheinlich müssen Sie den Stapelzeiger speichern, bevor Sie f aufrufen, und dann eine Kopie des Inhalts von (vorheriger Stapelzeiger..aktueller Stapelzeiger) erstellen.

    
Giovanni Funchal 16.11.2011 16:10
quelle

Tags und Links