Angenommen, ich habe eine generate_my_range
Klasse, die a modelliert range
(insbesondere ist regular
). Dann ist der folgende Code korrekt:
auto generate_my_range(int some_param) {
auto my_transform_op = [](const auto& x){ return do_sth(x); };
return my_custom_rng_gen(some_param) | ranges::views::transform(my_transform_op);
}
auto cells = generate_my_range(10) | ranges::to<std::vector>;
Wird my_custom_rng_gen(some_param)
vom (ersten) Rohrbetreiber als Wert genommen, oder habe ich eine baumelnde Referenz, wenn ich den generate_my_range
Bereich verlasse ?
Wäre es mit dem Funktionsaufruf dasselbe ranges::views::transform(my_custom_rng_gen(some_param),my_transform_op)
?
Wäre es richtig, wenn ich eine Wertreferenz verwenden würde? z.B:
auto generate_my_range(int some_param) {
auto my_transform_op = [](const auto& x){ return do_sth(x); };
auto tmp_ref = my_custom_rng_gen(some_param);
return tmp_ref | ranges::views::transform(my_transform_op);
}
Wenn Bereiche für diese Operationen Werte annehmen, was mache ich dann, wenn ich einen lrefue ref an einen Container übergebe? Soll ich ein ranges::views::all(my_container)
Muster verwenden?
Antworten:
In der Bereichsbibliothek gibt es zwei Arten von Operationen:
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
und:
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:
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. Wennmy_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:
Der Ausdruck gibt also alles
views::transform
zurück, was zurückgegeben wird.Lesen Sie nun die Dokumentation der Transformation:
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.
quelle
ranges::views::all(my_container)
? Und was ist, wenn ein Blick auf die Pipe übertragen wird? Erkennt es, dass ein Container oder eine Ansicht übergeben wurde? Muss es sein? Wie?my_custom_rng_gen
. Wie genau das Rohr und dietransform
Interaktion unter der Haube sind nicht wichtig. Der gesamte Ausdruck verwendet einen Bereich als Argument (einen Container oder eine Ansicht für einen Container) und gibt eine andere Ansicht für diesen Container zurück. Der Rückgabewert wird niemals den Container besitzen, da es sich um eine Ansicht handelt.Entnommen aus der Dokumentation zu range-v3 :
und
Da Sie gesagt haben, dass der temporäre Bereich als Container betrachtet werden kann, gibt Ihre Funktion eine baumelnde Referenz zurück.
Mit anderen Worten, Sie müssen sicherstellen, dass der zugrunde liegende Bereich die Ansicht überlebt, oder Sie haben Probleme.
quelle