Récemment, j'ai eu des suggestions pour utiliser span<T>
dans mon code, ou j'ai vu des réponses ici sur le site qui utilisent span
- soi-disant une sorte de conteneur. Mais - je ne trouve rien de tel dans la bibliothèque standard C++.
Alors, quel est ce mystérieux span<T>
, et pourquoi (ou quand) est-ce une bonne idée de l'utiliser si ce n'est pas standard?
Un span<T>
est:
struct { T * ptr; size_t length; }
avec un tas de méthodes pratiques.Il était auparavant appelé array_view
et même plus tôt array_ref
.
D'abord, quand pas pour l'utiliser:
std::sort
, std::find_if
, std::copy
et toutes ces fonctions basées sur des modèles super-génériques.Maintenant pour quand l'utiliser réellement:
Utilisez
span<T>
(respectivement,span<const T>
) au lieu d'unT*
libre (respectivementconst T*
) pour lequel vous avez la valeur de longueur. Donc, remplacez des fonctions comme:void read_into(int* buffer, size_t buffer_size);
avec:
void read_into(span<int> buffer);
Oh, les travées sont géniales! Utiliser un span
...
signifie que vous pouvez utiliser cette combinaison pointeur + longueur/début + fin, comme vous le feriez avec un conteneur de bibliothèque standard sophistiqué et fantaisiste, par exemple:
for (auto& x : my_span) { /* do stuff */ }
std::find_if(my_span.begin(), my_span.end(), some_predicate);
... mais avec absolument aucun des frais généraux que la plupart des classes de conteneurs encourent.
laisse parfois le compilateur faire plus de travail pour vous. Par exemple, ceci:
int buffer[BUFFER_SIZE];
read_into(buffer, BUFFER_SIZE);
devient ceci:
int buffer[BUFFER_SIZE];
read_into(buffer);
... qui fera ce que vous voudriez qu'il fasse. Voir aussi directive P.5 .
est l’alternative raisonnable de passer const vector<T>&
à des fonctions lorsque vous vous attendez à ce que vos données soient contiguës en mémoire. Pas plus se faire gronder par les gourous C++ haut et puissant.
span
auront un code de vérification des limites dans #ifndef NDEBUG
... #endif
)Il y a encore plus de motivation à utiliser span
s, ce que vous pouvez trouver dans directives de base de C++ - mais vous voyez la dérive.
C'est dans la bibliothèque standard - mais seulement à partir de C++ 20. La raison en est qu’elle est encore relativement nouvelle dans sa forme actuelle, conçue en conjonction avec le projet C++ core guidelines , qui ne prend forme que depuis 2015. (Bien que, comme le soulignent les commentateurs, elle a déjà été réalisée .)
Cela fait partie de GSL), la bibliothèque de support de --- (Core Guidelines . Implémentations:
gsl/span
span<T>
.L’implémentation GSL suppose généralement une plate-forme implémentant le support C++ 14 [ 14 ]. Ces implémentations alternatives à en-têtes simples ne dépendent pas des fonctionnalités GSL:
martinmoene/span-lite
nécessite C++ 98 ou version ultérieuretcbrindle/span
nécessite C++ 11 ou une version ultérieureNotez que vous pouvez l'utiliser avec les versions antérieures de la norme de langage - C++ 11 et C++ 14, pas seulement C++ 17.
Pour en savoir plus: Vous trouverez tous les détails et toutes les considérations de conception dans la proposition officielle finale avant C++ 17, P0122R7: span: bounds -safe vues pour les séquences d'objets par Neal Macintosh et Stephan J. Lavavej. C'est un peu long cependant. De plus, en C++ 20, la sémantique de la comparaison d'étendue a changé (à la suite de ce court article de Tony van Eerd).