Perché a std :: span mancano gli operatori di confronto?


10

Non è stato std::spanprogettato come un riferimento leggero alle sottoregioni di std::vector/ std::array/ plain array e simili? Non dovrebbe contenere anche operatori di confronto nella sua API, per essere coerenti con loro? Qual è stato il ragionamento alla base dell'esclusione?

Nota: per gli operatori di confronto, intendo sia il set completo ( <, <=, ...) o l'astronave<=>


Ottima domanda IMO, mi chiedo lo stesso. operator==manca anche. Esp. per il vettore trovo spesso conveniente confrontare direttamente. Potrebbe essere dovuto a difficoltà forse con i tipi di span di dimensione statica, anche se non sono sicuro.
martedì

Sembra che gsl :: span, da cui std :: span è versione non include neanche questi.
martedì

1
@DanielLangr perché non fare un confronto lessicografico come std::vectore std::arrayfare? Sono definiti proprio così per quei tipi già, quindi perché non qui.
Timo

2
Si noti che P0122R7 propone un confronto per span, ma l' attuale bozza di standard non lo include.
Daniel Langr,

1
@darune gsl::span ha (e ha sempre fatto) operatori di confronto. Li hanno appena spostati nella loro intestazione
Barry l'

Risposte:


3

Come ha sottolineato Daniel Langr , std::spanha operatori di confronto nella sua proposta iniziale P0122 . Questi operatori vengono quindi rimossi dal progetto di lavoro N4791 e i motivi sono indicati in P1085 .

In breve, copia e const per std::spansono "superficiali" (il che significa che la copia di un std::spannon copia i suoi elementi sottostanti, e una const std::spannon impedisce la modifica dei suoi elementi sottostanti), quindi i confronti, se presenti, dovrebbero anche essere "superficiali" per coerenza.

Quel documento fornisce i seguenti esempi:

Esempio 1:

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

Esempio 2:

void read_only(const T & x);

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

Le affermazioni in questi esempi potrebbero non riuscire se T = std::span, mentre non lo è per i tipi normali.

Si potrebbe sostenere che std::string_viewabbia una copia superficiale ma confronti profondi. P1085 ha anche una spiegazione per questo:

Questa corrispondenza string_view, tuttavia, string_viewnon può modificare gli elementi a cui punta, e quindi la copia superficiale di string_viewpuò essere considerata simile a un'ottimizzazione di copia su scrittura.


Si noti che nulla impedisce al proprietario dell'array di caratteri di modificare la memoria originale mentre std::string_viewpunta ad essa. Quindi, diciamo, std::map<std::span<T>, U>è rotto come std::map<std::string_view, U>. IMHO, std::string_viewnon dovrebbe contenere nemmeno operatori di confronto.
Lyberta il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.