Na biblioteca de intervalos, existem dois tipos de operações:
- visualizações preguiçosas e que exijam a existência do contêiner subjacente.
- ações ansiosas e, como resultado, produzem novos contêineres (ou modificam os existentes)
As visualizações são leves. Você os passa por valor e exige que os contêineres subjacentes permaneçam válidos e inalterados.
Na documentação do range-v3
Uma visualização é um invólucro leve que apresenta uma visualização de uma sequência subjacente de elementos de alguma maneira personalizada, sem modificá-la ou copiá-la. As visualizações são baratas para criar e copiar e possuem semânticas de referência não proprietárias.
e:
Qualquer operação no intervalo subjacente que invalide seus iteradores ou sentinelas também invalidará qualquer exibição que se refira a qualquer parte desse intervalo.
A destruição do contêiner subjacente obviamente invalida todos os iteradores para ele.
Em seu código você está specifially usando visualizações - Você usa ranges::views::transform
. O cachimbo é apenas um açúcar sintático para facilitar a escrita do jeito que está. Você deve olhar a última coisa no tubo para ver o que produz - no seu caso, é uma visão.
Se não houvesse operador de tubo, provavelmente seria algo parecido com isto:
ranges::views::transform(my_custom_rng_gen(some_param), my_transform_op)
se houvesse várias transformações conectadas dessa maneira, você poderá ver como seria feio.
Assim, se my_custom_rng_gen
produz algum tipo de contêiner, que você transforma e depois retorna, esse contêiner é destruído e você tem referências pendentes da sua exibição. Se my_custom_rng_gen
houver outra visão de um contêiner que mora fora desses escopos, está tudo bem.
No entanto, o compilador deve poder reconhecer que você está aplicando uma exibição em um contêiner temporário e receber um erro de compilação.
Se você deseja que sua função retorne um intervalo como um contêiner, é necessário "materializar" explicitamente o resultado. Para isso, use o ranges::to
operador dentro da função.
Atualização: para ser mais explícito em relação ao seu comentário "onde a documentação diz que a faixa / tubulação de composição obtém e armazena uma visualização?"
Pipe é apenas um açúcar sintático para conectar coisas em uma expressão fácil de ler. Dependendo de como é usado, ele pode ou não retornar uma exibição. Depende do argumento do lado direito. No seu caso, é:
`<some range> | ranges::views::transform(...)`
Portanto, a expressão retorna o que quer que views::transform
retorne.
Agora, lendo a documentação da transformação:
Abaixo está uma lista dos combinadores de faixa lenta, ou visualizações, que o Range-v3 fornece, e um resumo sobre como cada um deles deve ser usado.
[...]
views::transform
Dado um intervalo de origem e uma função unária, retorne um novo intervalo em que cada elemento de resultado é o resultado da aplicação da função unária a um elemento de origem.
Portanto, ele retorna um intervalo, mas, como é um operador lento, esse intervalo é uma visualização, com toda a sua semântica.