Frage

Ich habe in vielen meiner Python-Programme mit der Ausbeute und es wirklich löscht den Code in vielen Fällen auf. Ich darüber gebloggt und es ist einer meiner Website beliebte Seiten.

C # auch Angebote ergeben -. Es über state-keeping in der Anruferseite implementiert ist, eine automatisch generierte Klasse erfolgt durch, die den Staat, lokale Variablen der Funktion hält, etc

Ich bin derzeit Lesung über C ++ 0x und ihre Ergänzungen; und beim Lesen über die Implementierung von Lambdas in C ++ 0x, finde ich heraus, dass es auch über automatisch generierte Klassen getan wurde, ausgestattet mit Operator (), um den Lambda-Code zu speichern. Die natürliche Frage in meinem Kopf gebildet: sie taten es für Lambda-Ausdrücke, warum haben sie es nicht als Unterstützung der „Ausbeute“ auch

Sicher können sie den Wert von Co-Routinen sehen ... so kann ich nur vermuten, dass sie denken, Makro-basierten Implementierungen (wie Simon Tathams ) als vollwertiger Ersatz. Sie sind jedoch nicht aus vielen Gründen. Rufenen gehütetes Zustand, nichtablaufinvarianten, Makro-basierte (das allein Grund genug ist), etc

Edit: yield hängt nicht von der Garbage Collection, Fäden oder Fasern. Sie können Simons Artikel zu sehen, dass ich rede über die Compiler eine einfache Transformation zu tun, wie lesen:

int fibonacci() {
    int a = 0, b = 1;
    while (true) {
        yield a;
        int c = a + b;
        a = b;
        b = c;
    }
}

In:

struct GeneratedFibonacci {
    int state;
    int a, b;

    GeneratedFibonacci() : state (0), a (0), b (1) {}

    int operator()() {
        switch (state) {
        case 0:
            state = 1;
            while (true) {
                return a;

        case 1:
                int c = a + b;
                a = b;
                b = c;
            }
        }
    }
}

Die Garbage-Collection? Nein Themen? Nr Fasern? Nein. Einfache Transformation? Argumentieren, ja.

War es hilfreich?

Lösung

  

Sie tun es für Lambda-Ausdrücke, warum nicht sie es Ausbeute für die Unterstützung, auch?

Überprüfen Sie die Papiere . Hat jemand schlagen vor?

  

... kann ich nur vermuten, dass sie Makro-basierten Implementierungen betrachten ein adäquater Ersatz sein.

Nicht unbedingt. Ich bin sicher, sie wissen, dass solche Makro Lösungen existieren, aber sie ist nicht genug Motivation, auf seinem eigenen zu ersetzen, neue Funktionen übergeben werden.


Auch wenn es verschiedene Fragen rund um ein neues Schlüsselwort, die mit neuer Syntax überwunden werden könnte, wie zum Beispiel wurde für lambdas getan und mit Auto als Funktion Rückgabetyp.

Radically neue Funktionen brauchen starke Treiber (das heißt Personen) vollständig zu analysieren und Push-Funktionen durch den Ausschuss, wie sie es immer viele Leute skeptisch einer radikalen Veränderung haben. Also auch nicht anwesend, was Sie als starker technischer Grund gegen eine Ausbeute Konstrukt sehen würden, kann es immer noch nicht genug Unterstützung gewesen sein.

Aber im Grunde hat sich die C ++ Standardbibliothek ein anderes Konzept von Iteratoren umarmte, als Sie mit Ausbeute sehen würde. Vergleichen Sie bis zu Pythons Iteratoren, die nur erfordern zwei Operationen:

  1. an_iter.next () gibt den nächsten Punkt oder wirft StopIteration (next () builtin in 2.6 enthalten stattdessen ein Verfahren zur Verwendung)
  2. iter (an_iter) gibt an_iter (so Sie Iterables und Iteratoren identisch in Funktionen behandeln können)

C ++ 's Iteratoren verwendet wird paarweise (die vom gleichen Typ sein müssen), sind in Kategorien unterteilt, wäre es eine semantische Verschiebung Übergang in etwas empfänglicher eine Ausbeute Konstrukt sein, und das Schalt passen würde nicht gut mit Begriffen (die seit fallen gelassen worden, aber das kam relativ spät). Zum Beispiel finden Sie in der Begründung für (zu Recht, wenn enttäuschende) bereichsbasierte meinen Kommentars Ablehnung auf Wechsel in eine Form für Schleifen, die diese andere Form des Iterator viel einfacher machen würden, zu schreiben.

Um konkret klären, was ich über die verschiedenen Formen Iterator bedeuten: Ihre generierter Code Beispiel Bedürfnisse andere Art die Iteratortyp sowie dazugehörige Maschinen für den Erwerb und Erhalt dieser Iteratoren zu sein. Nicht, dass es nicht verarbeitet werden kann, aber es ist nicht so einfach, wie man auf dem ersten vorstellen kann. Die eigentliche Komplexität ist die „einfache Transformation“ Ausnahmen für „lokal“ Variablen (einschließlich während der Bauphase) zu respektieren, Steuern Lebensdauer von „lokalen“ Variablen in lokalen Bereichen innerhalb des Generators (die meisten würden über Anrufe müssen gespeichert werden), und so weiter.

Andere Tipps

Ich kann nicht sagen, warum sie nicht so etwas wie dies hinzugefügt haben, aber im Fall von Lambda-Ausdrücke, sie waren nicht nur hinzugefügt, um die Sprache auch nicht.

Sie begannen Leben als Bibliothek Implementierung in Boost, die bewiesen, dass

  • lambdas sind weithin nützlich: eine Menge Leute sie benutzen, wenn sie verfügbar sind, und dass
  • eine Bibliothek Implementierung in C ++ 03 leidet unter einer Reihe von Mängeln.

Auf dieser Grundlage beschloss der Ausschuß zu übernehmen eine Art von Lambda-Ausdrücke in C ++ 0x, und ich glaube, sie zunächst mit dem Hinzufügen von allgemeiner Sprache verfügt experimentierte ein besser Bibliothek Implementierung als Boost-hat.

Und schließlich, sie machte es eine Kern Sprache-Funktion, weil sie keine andere Wahl hatten., Weil es nicht möglich war, eine gut genug, um Bibliothek Implementierung

Neue Kernsprachfunktionen sind nicht nur auf die Sprache hinzugefügt, weil sie wie eine gute Idee zu sein scheint. Der Ausschuss ist sehr nur ungern, um sie hinzuzufügen, und die Funktion in Frage wirklich muss sich beweisen. Es muss gezeigt werden, dass das Merkmal:

  • möglich in den Compiler zu implementieren,
  • geht ein echtes Bedürfnis zu lösen, und
  • , dass eine Bibliothek Implementierung wäre nicht gut genug sein.

Im Fall, wenn ein yield Stichwort, wissen wir, dass der erste Punkt gelöst werden kann. Wie Sie gezeigt haben, ist es eine ziemlich einfache Transformation, die mechanisch durchgeführt werden kann.

Der zweite Punkt ist schwierig. Wie viel von einer Notwendigkeit dafür ist da? Wie weit verbreitet die Bibliothek Implementierungen sind, die es gibt? Wie viele Menschen haben darum gebeten, oder unterbreiteten Vorschläge für sie?

Der letzte Punkt scheint zu passieren. Zumindest in C ++ 03, leidet eine Bibliothek Implementierung einige Mängel, wie Sie sagten, die könnte eine Kernsprache Implementierung rechtfertigen. Könnte eine bessere Bibliothek Implementierung obwohl in C ++ 0x gemacht werden?

So vermute ich, das Hauptproblem ist wirklich ein Mangel an Interesse. C ++ ist bereits eine große Sprache, und niemand will es größer werden, es sei denn die Merkmale hinzugefügt werden wirklich wert. Ich vermute, dass dies einfach nicht nützlich genug ist.

ein Schlüsselwort hinzuzufügen, ist immer schwierig, weil es zuvor gültigen Code ungültig. Sie versuchen, dass mit einer Codebasis so groß wie C in einer Sprache zu vermeiden ++.

Die Entwicklung von C ++ ist ein öffentlicher Prozess. Wenn Sie yield fühlen sollte es sein, eine entsprechende Anfrage an den C ++ Standard Ausschuss formulieren.

Sie werden Ihre Antwort erhalten, direkt von den Menschen, die die Entscheidung getroffen haben.

So sieht es aus wie es nicht in C ++ 11 geschaffen hat, oder C ++ 14, könnte aber auf dem Weg sein, um C ++ 17. Werfen Sie einen Blick auf der Vorlesung C ++ Koroutinen, einen negativen Kopf Abstraktion von CppCon2015 und das Papier hier .

Um es zusammenzufassen, sie arbeiten c ++ Funktionen zu erweitern Ausbeute zu haben und erwarten als Merkmale von Funktionen. Sieht aus wie sie haben eine erste Implementierung in Visual Studio 2015 nicht sicher, ob Klirren noch eine Implementierung hat. Auch scheint es sich möglicherweise einige Probleme sein mit der Verwendung von Ertrag und await wie die Schlüsselwörter.

Die Präsentation ist interessant, weil er spricht, wie viel es Netzwerk-Code vereinfacht, wo Sie warten auf Daten in kommen, um die Abfolge der Verarbeitung fortzusetzen. Überraschenderweise sieht es aus wie diese neuen Koroutinen Ergebnisse in schneller mit / weniger Code als das, was man heute tun würde. Es ist eine große Präsentation.

Die fortsetzbar Funktionen Vorschlag für C ++ finden Sie hier .

In der Regel können Sie verfolgen, was von den Ausschuss Papiere los ist , obwohl es besser für Spur zu halten, anstatt mit einem besonderen Problem aufzuzublicken.

Eine Sache, über den C ++ Ausschuss zu erinnern ist, dass es ein Freiwilliger Ausschuß ist, und kann nicht erreichen, alles, was es will. Zum Beispiel gab es keine Hash-Typen Karte in dem ursprünglichen Standard, weil sie es nicht schaffen könnten, um es in der Zeit. Es könnte sein, dass sich niemand im Ausschuss war, der über yield genug gepflegt und was es zu machen ist sicher nicht die Arbeit wurde getan.

Der beste Weg wäre, um herauszufinden, um ein aktives Mitglied des Ausschusses zu stellen.

Nun, für ein solches triviales Beispiel, wie das, das einzige Problem, das ich sehe ist, dass std::type_info::hash_code() constexpr nicht angegeben ist. Ich glaube, eine konforme Implementierung noch es so machen könnte und unterstützen diese. Wie auch immer das eigentliche Problem eindeutige Kennungen ist zu erhalten, so könnte es eine andere Lösung sein. (Offensichtlich lieh ich mir Ihr „Hauptschalter“ Konstrukt, danke.)

#define YIELD(X) do { \
    constexpr size_t local_state = typeid([](){}).hash_code(); \
    return (X); state = local_state; case local_state: ; } \
while (0)

Verbrauch:

struct GeneratedFibonacci {
    size_t state;
    int a, b;

    GeneratedFibonacci() : state (0), a (0), b (1) {}

    int operator()() {
        switch (state) {
        case 0:
            while (true) {
                YIELD( a );
                int c = a + b;
                a = b;
                b = c;
            }
        }
    }
}

Hmm, würde sie auch zu garantieren müssen, dass der Hash nicht 0 Kein großes Problem da. Und ein DONE Makro ist einfach zu implementieren.


Das eigentliche Problem ist das, was passiert, wenn man aus einem Rahmen mit lokalen Objekten zurück. Es gibt keine Hoffnung der Rettung aus einem Stapelrahmen in einer C-basierten Sprache. Die Lösung ist eine echte Koroutine zu verwenden, und C ++ 0x tut direkt Adresse, die mit Fäden und Futures.

Betrachten Sie diesen Generator / Koroutine:

void ReadWords() {
    ifstream f( "input.txt" );

    while ( f ) {
        string s;
        f >> s;
        yield s;
    }
}

Wenn ein ähnlicher Trick für yield verwendet wird, f am ersten yield zerstört, und es ist illegal, die Schleife, nachdem es fortzusetzen, denn man kann nicht goto oder switch vorbei an einer nicht-POD Objektdefinition.

gibt es mehrere Implementierung von Koroutinen als User-Space-Bibliotheken gewesen. Allerdings, und hier ist der Deal, verlassen diese Implementierungen auf Nicht-Standard-Details. Zum Beispiel wird nirgendwo auf dem C ++ Standard festgelegt, wie Stapelrahmen gehalten werden. Die meisten Implementierungen kopieren Sie einfach den Stapel, weil das ist, wie die meisten c ++ Implementierungen Arbeit

in Bezug auf Normen, c ++ Koroutine Unterstützung dazu beigetragen haben, könnte durch die Festlegung von Stapelrahmen zu verbessern.

Eigentlich ‚Hinzufügen‘ um es in die Sprache nicht eine gute Idee zu mir klingt, denn, dass Sie mit einer ‚gut genug‘ Implementierung für die meisten Fälle bleiben würde, die vollständig vom Compiler abhängig ist. Für die Fälle, in denen ein Koroutine Angelegenheiten verwenden, dies sowieso nicht akzeptabel ist

stimmt mit @Potatoswatter zuerst.

Koroutine Zur Unterstützung ist nicht das Gleiche wie die Unterstützung für Lambda-Ausdrücke und nicht, dass einfache Transformation wie mit Duff-Gerät wiedergegeben.

Sie müssen voll asymmetrische Koroutinen (stackful ) wie Generatoren in Python zu arbeiten. Die Umsetzung des Simon Tathams und Chris' beide stackless sind, während Boost.Coroutine ist ein stackfull man es ist schwer aber.

Leider C ++ 11 noch nicht über yield für Koroutinen noch, vielleicht C ++ 1J;)

PS: Wenn Sie wirklich, wie Python-Stil Generatoren, haben einen Blick auf dieser .

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top