Nella libreria degli intervalli ci sono due tipi di operazioni:
- viste pigre e che richiedono l'esistenza del contenitore sottostante.
- azioni che sono desiderose e di conseguenza producono nuovi contenitori (o modificano quelli esistenti)
Le viste sono leggere. Li passi per valore e richiedi che i contenitori sottostanti rimangano validi e invariati.
Dalla documentazione di range-v3
Una vista è un wrapper leggero che presenta una vista di una sequenza di elementi sottostante in qualche modo personalizzato senza modificarla o copiarla. Le viste sono economiche da creare e copiare e hanno una semantica di riferimento non proprietaria.
e:
Qualsiasi operazione sull'intervallo sottostante che invalida i suoi iteratori o sentinelle invaliderà anche qualsiasi vista che si riferisce a qualsiasi parte di tale intervallo.
La distruzione del contenitore sottostante invalida ovviamente tutti gli iteratori ad esso.
Nel tuo codice stai specificatamente usando le viste - Tu usi ranges::views::transform
. La pipa è semplicemente uno zucchero sintattico per facilitare la scrittura così com'è. Dovresti guardare l'ultima cosa nella pipa per vedere cosa produci - nel tuo caso, è una vista.
Se non ci fosse un operatore di tubi, probabilmente sarebbe simile a questo:
ranges::views::transform(my_custom_rng_gen(some_param), my_transform_op)
se ci fossero più trasformazioni collegate in questo modo puoi vedere quanto sarebbe brutto.
Pertanto, se my_custom_rng_gen
produce un tipo di contenitore, che trasformi e poi ritorni, quel contenitore viene distrutto e hai riferimenti penzolanti dalla tua vista. Se my_custom_rng_gen
è un'altra visione di un contenitore che vive al di fuori di questi ambiti, tutto va bene.
Tuttavia, il compilatore dovrebbe essere in grado di riconoscere che stai applicando una vista su un contenitore temporaneo e colpirti con un errore di compilazione.
Se si desidera che la funzione restituisca un intervallo come contenitore, è necessario "materializzare" esplicitamente il risultato. Per questo, utilizzare l' ranges::to
operatore all'interno della funzione.
Aggiornamento: per essere più esplicito riguardo al tuo commento "dove dice la documentazione che comporre range / piping prende e memorizza una vista?"
Pipe è semplicemente uno zucchero sintattico per connettere le cose in un'espressione di facile lettura. A seconda di come viene utilizzato, può o meno restituire una vista. Dipende dall'argomento sul lato destro. Nel tuo caso è:
`<some range> | ranges::views::transform(...)`
Quindi l'espressione restituisce qualunque cosa views::transform
ritorni.
Ora, leggendo la documentazione della trasformazione:
Di seguito è riportato un elenco dei combinatori o viste di intervallo pigro forniti da Range-v3 e un blurb su come ciascuno di essi deve essere utilizzato.
[...]
views::transform
Dato un intervallo di origine e una funzione unaria, restituisce un nuovo intervallo in cui ciascun elemento risultato è il risultato dell'applicazione della funzione unaria a un elemento sorgente.
Quindi restituisce un intervallo, ma poiché è un operatore pigro, quell'intervallo che restituisce è una vista, con tutta la sua semantica.