W bibliotece zakresów istnieją dwa rodzaje operacji:
- widoki leniwe i wymagające istnienia podstawowego kontenera.
- chętne działania, w wyniku których powstają nowe pojemniki (lub modyfikują istniejące)
Widoki są lekkie. Przekazujesz je według wartości i wymagasz, aby kontenery leżące poniżej były ważne i niezmienione.
Z dokumentacji zakresów-v3
Widok jest lekkim opakowaniem, które przedstawia widok sekwencji podstawowych elementów w niestandardowy sposób bez ich mutowania lub kopiowania. Widoki są tanie w tworzeniu i kopiowaniu oraz mają nie-własnościową semantykę odniesienia.
i:
Wszelkie operacje na podstawowym zakresie, które unieważniają jego iteratory lub wartowniki, również unieważniają każdy widok, który odnosi się do dowolnej części tego zakresu.
Zniszczenie leżącego pod nim kontenera oczywiście unieważnia wszystkie iteratory.
W swoim kodzie używasz widoków - korzystasz ranges::views::transform
. Fajka jest cukrem syntaktycznym, co ułatwia pisanie takim, jakim jest. Powinieneś spojrzeć na ostatnią rzecz w rurze, aby zobaczyć, co produkujesz - w twoim przypadku jest to widok.
Gdyby nie było operatora potoku, prawdopodobnie wyglądałby mniej więcej tak:
ranges::views::transform(my_custom_rng_gen(some_param), my_transform_op)
gdyby w ten sposób było połączonych wiele transformacji, można zobaczyć, jak brzydko by to zrobiło.
Tak więc, jeśli my_custom_rng_gen
produkuje jakiś kontener, który przekształcasz, a następnie powrócisz, kontener ten zostanie zniszczony i będziesz mieć wiszące odniesienia z twojego widoku. Jeśli my_custom_rng_gen
jest inny widok kontenera, który mieszka poza tymi zakresami, wszystko jest w porządku.
Jednak kompilator powinien być w stanie rozpoznać, że stosujesz widok do tymczasowego kontenera i uderzył cię błąd kompilacji.
Jeśli chcesz, aby funkcja zwróciła zakres jako kontener, musisz jawnie „zmaterializować” wynik. W tym celu użyj ranges::to
operatora w ramach funkcji.
Aktualizacja: Aby uzyskać więcej informacji na temat komentarza „gdzie dokumentacja mówi, że komponowanie zakresu / orurowania bierze i przechowuje widok?”
Fajka jest jedynie cukrem syntaktycznym, który łączy rzeczy w łatwy do odczytania sposób. W zależności od tego, jak jest używany, może on zwrócić widok. To zależy od argumentu po prawej stronie. W twoim przypadku jest to:
`<some range> | ranges::views::transform(...)`
Zatem wyrażenie zwraca cokolwiek, co views::transform
zwraca.
Teraz czytając dokumentację transformacji:
Poniżej znajduje się lista leniwych kombiatorów zakresu lub widoków, które zapewnia Range-v3, oraz informacja o tym, jak każdy z nich jest przeznaczony do użycia.
[...]
views::transform
Biorąc pod uwagę zakres źródłowy i funkcję jednoargumentową, zwróć nowy zakres, w którym każdy element wynikowy jest wynikiem zastosowania funkcji jednoargumentowej do elementu źródłowego.
Dlatego zwraca zakres, ale ponieważ jest to operator leniwy, że zakres zwraca się widokiem, ze wszystkimi jego semantyki.