У бібліотеці діапазонів є два види операцій:
- погляди, які ліниві і вимагають існування базового контейнера.
- дії, які прагнуть, і в результаті створюють нові контейнери (або змінюють існуючі)
Погляди легкі. Ви передаєте їх за значенням і вимагаєте, щоб базові контейнери залишалися дійсними та незмінними.
З документації на діапазони-v3
Вид - це легка обгортка, яка представляє вигляд основної послідовності елементів певним чином, не мутуючи і не копіюючи її. Погляди дешеві для створення та копіювання та мають невласницьку довідкову семантику.
і:
Будь-яка операція в нижньому діапазоні, що визнає недійсним її ітераторів або дозорних, також призведе до недійсності будь-якого представлення, яке стосується будь-якої частини цього діапазону.
Знищення базового контейнера очевидно збиває з нього всіх ітераторів.
У своєму коді ви спеціально використовуєте представлення даних - Ви використовуєтеranges::views::transform
. Труба - це лише синтаксичний цукор, який дозволяє легко писати так, як є. Вам слід подивитися на останнє, що знаходиться в трубі, щоб побачити, що ви виробляєте - у вашому випадку це вид.
Якби не було трубного оператора, це, мабуть, виглядало б приблизно так:
ranges::views::transform(my_custom_rng_gen(some_param), my_transform_op)
якби було пов'язано кілька перетворень таким чином, ви можете бачити, наскільки потворним це було б.
Таким чином, якщо my_custom_rng_gen
виробляється якийсь контейнер, який ви трансформуєте і потім повертаєте, той контейнер знищується, і у вас є звисаючі посилання зі свого погляду. Якщо my_custom_rng_gen
інший вид на контейнер, який живе за межами цих областей, все добре.
Однак компілятор повинен бути в змозі визнати, що ви застосовуєте подання на тимчасовий контейнер і вдарив вас про помилку компіляції.
Якщо ви хочете, щоб ваша функція повертала діапазон як контейнер, потрібно чітко "матеріалізувати" результат. Для цього використовуйте ranges::to
оператор у межах функції.
Оновлення: щоб бути більш реплікованим щодо Вашого коментаря, "де в документації написано, що діапазон складання / трубопровід займає і зберігає вигляд?"
Труба - це просто синтаксичний цукор для з'єднання речей у легкому для читання виразі. Залежно від способу його використання, він може або не може повернути погляд. Це залежить від правого аргументу. У вашому випадку це:
`<some range> | ranges::views::transform(...)`
Отже вираз повертає те, що views::transform
повертається.
Тепер, прочитавши документацію перетворення:
Нижче наводиться перелік комбінаторів лінивого діапазону чи виду, які надає Range-v3, і розмиття про те, як кожен з них планується використовувати.
[...]
views::transform
Враховуючи діапазон джерела та одинарну функцію, поверніть новий діапазон, коли кожен елемент результату є результатом застосування одинарної функції до елемента джерела.
Таким чином, він повертає діапазон, але оскільки це ледачий оператор, цей діапазон, який він повертає, - це погляд, з усією його семантикою.