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<=>

GreenScape
la source
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.

xskxzr
la source
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