In der Bereichsbibliothek gibt es zwei Arten von Operationen:
- Ansichten, die faul sind und für die der zugrunde liegende Container vorhanden sein muss.
- Aktionen, die eifrig sind und als Ergebnis neue Container produzieren (oder vorhandene modifizieren)
Ansichten sind leicht. Sie übergeben sie als Wert und verlangen, dass die zugrunde liegenden Container gültig und unverändert bleiben.
Aus der Dokumentation zu range-v3
Eine Ansicht ist ein kompakter Wrapper, der eine Ansicht einer zugrunde liegenden Folge von Elementen auf benutzerdefinierte Weise darstellt, ohne sie zu mutieren oder zu kopieren. Ansichten sind billig zu erstellen und zu kopieren und haben eine nicht besitzende Referenzsemantik.
und:
Jede Operation für den zugrunde liegenden Bereich, die seine Iteratoren oder Sentinels ungültig macht, macht auch jede Ansicht ungültig, die sich auf einen Teil dieses Bereichs bezieht.
Die Zerstörung des zugrunde liegenden Containers macht offensichtlich alle Iteratoren ungültig.
In Ihrem Code verwenden Sie speziell Ansichten - Sie verwenden ranges::views::transform
. Die Pfeife ist lediglich ein syntaktischer Zucker, um das Schreiben so zu erleichtern, wie es ist. Sie sollten sich das Letzte in der Pfeife ansehen, um zu sehen, was Sie produzieren - in Ihrem Fall ist es eine Ansicht.
Wenn es keinen Rohrbetreiber gäbe, würde es wahrscheinlich ungefähr so aussehen:
ranges::views::transform(my_custom_rng_gen(some_param), my_transform_op)
Wenn auf diese Weise mehrere Transformationen verbunden wären, können Sie sehen, wie hässlich es werden würde.
Wenn also my_custom_rng_gen
eine Art Container erzeugt wird, den Sie transformieren und dann zurückgeben, wird dieser Container zerstört und Sie haben baumelnde Referenzen aus Ihrer Sicht. Wenn my_custom_rng_gen
es sich um eine andere Ansicht eines Containers handelt, der außerhalb dieser Bereiche lebt, ist alles in Ordnung.
Der Compiler sollte jedoch erkennen können, dass Sie eine Ansicht auf einen temporären Container anwenden, und Sie mit einem Kompilierungsfehler treffen.
Wenn Ihre Funktion einen Bereich als Container zurückgeben soll, müssen Sie das Ergebnis explizit "materialisieren". Verwenden Sie dazu den ranges::to
Operator innerhalb der Funktion.
Update: Um Ihren Kommentar genauer zu beschreiben : "Wo steht in der Dokumentation, dass das Erstellen von Bereichen / Rohrleitungen eine Ansicht benötigt und speichert?"
Pipe ist lediglich ein syntaktischer Zucker, um Dinge in einem leicht lesbaren Ausdruck zu verbinden. Je nachdem, wie es verwendet wird, wird möglicherweise eine Ansicht zurückgegeben oder nicht. Es kommt auf das Argument auf der rechten Seite an. In Ihrem Fall ist es:
`<some range> | ranges::views::transform(...)`
Der Ausdruck gibt also alles views::transform
zurück, was zurückgegeben wird.
Lesen Sie nun die Dokumentation der Transformation:
Unten finden Sie eine Liste der Lazy Range-Kombinatoren oder -Ansichten, die Range-v3 bereitstellt, sowie einen Klappentext darüber, wie die einzelnen Funktionen verwendet werden sollen.
[...]
views::transform
Geben Sie bei einem gegebenen Quellbereich und einer unären Funktion einen neuen Bereich zurück, in dem jedes Ergebniselement das Ergebnis der Anwendung der unären Funktion auf ein Quellelement ist.
Es gibt also einen Bereich zurück, aber da es sich um einen Lazy-Operator handelt, handelt es sich bei dem zurückgegebenen Bereich um eine Ansicht mit all ihrer Semantik.