Dans la bibliothèque de plages, il existe deux types d'opérations:
- vues qui sont paresseuses et nécessitent que le conteneur sous-jacent existe.
- actions qui sont désireuses, et produisent de nouveaux conteneurs en conséquence (ou modifiez ceux existants)
Les vues sont légères. Vous les transmettez par valeur et exigez que les conteneurs sous-jacents restent valides et inchangés.
De la documentation gammes-v3
Une vue est un wrapper léger qui présente une vue d'une séquence sous-jacente d'éléments d'une manière personnalisée sans la muter ou la copier. Les vues sont bon marché à créer et à copier et ont une sémantique de référence sans propriétaire.
et:
Toute opération sur la plage sous-jacente qui invalide ses itérateurs ou sentinelles invalidera également toute vue faisant référence à une partie de cette plage.
La destruction du conteneur sous-jacent invalide évidemment tous ses itérateurs.
Dans votre code, vous utilisez spécifiquement des vues - Vous utilisez ranges::views::transform
. La pipe est simplement un sucre syntaxique qui facilite l'écriture telle qu'elle est. Vous devriez regarder la dernière chose dans le tuyau pour voir ce que vous produisez - dans votre cas, c'est une vue.
S'il n'y avait pas d'opérateur de tuyau, cela ressemblerait probablement à ceci:
ranges::views::transform(my_custom_rng_gen(some_param), my_transform_op)
s'il y avait plusieurs transformations connectées de cette façon, vous pouvez voir à quel point cela deviendrait laid.
Ainsi, si my_custom_rng_gen
produit une sorte de conteneur, que vous transformez puis renvoyez, ce conteneur est détruit et vous avez des références pendantes de votre vue. Si my_custom_rng_gen
c'est une autre vue d'un conteneur qui vit en dehors de ces étendues, tout va bien.
Cependant, le compilateur doit être capable de reconnaître que vous appliquez une vue sur un conteneur temporaire et de vous rencontrer avec une erreur de compilation.
Si vous souhaitez que votre fonction renvoie une plage en tant que conteneur, vous devez explicitement «matérialiser» le résultat. Pour cela, utilisez l' ranges::to
opérateur dans la fonction.
Mise à jour: Pour être plus explicite concernant votre commentaire "où la documentation indique-t-elle que la composition de la plage / des tuyaux prend et stocke une vue?"
La pipe est simplement un sucre syntaxique pour relier les choses dans une expression facile à lire. Selon la façon dont il est utilisé, il peut ou non renvoyer une vue. Cela dépend de l'argument de droite. Dans votre cas, c'est:
`<some range> | ranges::views::transform(...)`
Ainsi, l'expression renvoie tout ce qui views::transform
retourne.
Maintenant, en lisant la documentation de la transformation:
Vous trouverez ci-dessous une liste des combinateurs de plage paresseux, ou vues, que Range-v3 fournit, et un texte explicatif sur la façon dont chacun est destiné à être utilisé.
[...]
views::transform
Étant donné une plage source et une fonction unaire, renvoyez une nouvelle plage où chaque élément de résultat est le résultat de l'application de la fonction unaire à un élément source.
Il renvoie donc une plage, mais comme il s'agit d'un opérateur paresseux, cette plage qu'il renvoie est une vue, avec toute sa sémantique.