Pourquoi std :: span n'a pas d'opérateurs de comparaison?


10

N'est-ce pas std::spanconçu comme une référence légère aux sous-régions du tableaustd::vector / std::array/ plain et similaires? Ne devrait-il pas également contenir des opérateurs de comparaison dans son API, pour être cohérent avec eux? Quel était le raisonnement derrière l'exclusion?

Note: par les opérateurs de comparaison, je veux dire soit l'ensemble ( <, <=, ...) ou le vaisseau spatial<=>


Grande question OMI, je me demande la même chose. operator==est également manquant. Esp. pour le vecteur, je trouve souvent pratique de comparer directement. Cela pourrait être dû à des difficultés avec les types d'étendue de taille statique, bien que je ne sois pas sûr.
darune

Il ressemble à gsl :: span, à partir duquel std :: span est versionné ne les inclut pas non plus.
darune

1
@DanielLangr pourquoi pas une comparaison lexicographique comme std::vectoret std::arrayfaire? Ils sont déjà définis comme ça pour ces types, alors pourquoi pas ici.
Timo

2
Notez que P0122R7 propose une comparaison pour span, mais le projet de norme actuel ne l'inclut pas.
Daniel Langr

1
@darune gsl::span ne (et a toujours fait) ont des opérateurs de comparaison. Ils les ont juste déplacés dans leur propre tête
Barry

Réponses:


3

Comme l'a souligné Daniel Langr , std::spana des opérateurs de comparaison dans sa proposition initiale P0122 . Ces opérateurs sont ensuite supprimés depuis le projet de travail N4791 , et les raisons sont indiquées dans P1085 .

En bref, copy et const for std::spansont "superficiels" (ce qui signifie que la copie d'un std::spanne copie pas ses éléments sous-jacents et qu'un const std::spann'empêche pas la modification de ses éléments sous-jacents), donc les comparaisons, si elles existent, doivent également être "superficielles" pour la cohérence.

Ce document donne les exemples suivants:

Exemple 1:

T oldx = x;
change(x);
assert(oldx != x);
return oldx;

Exemple 2:

void read_only(const T & x);

void f()
{
  T tmp = x;
  read_only(x);
  assert(tmp == x);
}

Les assertions de ces exemples peuvent échouer si T = std::span, alors que ce n'est pas le cas pour les types réguliers.

On peut dire que la std::string_viewcopie est superficielle mais que les comparaisons sont profondes. P1085 a également une explication à cela:

Cela correspond string_view, mais string_viewne peut pas modifier les éléments vers lesquels il pointe, et donc la copie superficielle de string_viewpeut être considérée comme similaire à une optimisation de copie sur écriture.


Notez que rien n'empêche le propriétaire du tableau de caractères de modifier le stockage d'origine tout en le std::string_viewpointant. Donc, disons, std::map<std::span<T>, U>est aussi cassé que std::map<std::string_view, U>. À mon humble avis, std::string_viewne devrait pas non plus contenir d'opérateurs de comparaison.
Lyberta
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.