2016-03-23 10 views
7

Il seguente programma non viene compilato. Ma se non commento fuori operator==, compila. Perché operator== è nuovamente necessaria quando ho già fornisco FooEqualImpossibile confrontare std :: unorded_set con KeyEqual personalizzato

#include <cstddef> 
#include <unordered_set> 

struct Foo { 
}; 

struct FooHasher { 
    size_t operator()(const Foo&) const { 
    return 1; 
    } 
}; 

struct FooEqual { 
    bool operator()(const Foo& lhs, const Foo& rhs) const { 
    return true; 
    } 
}; 

// bool operator==(const Foo& lhs, const Foo& rhs) { 
// return true; 
// } 

int main() { 
    std::unordered_set<Foo, FooHasher, FooEqual> s1; 
    std::unordered_set<Foo, FooHasher, FooEqual> s2; 
    (void)(s1 == s2); 
    return 0; 
} 
+0

Deve essere un bug nell'implementazione ... a meno che la specifica non dica che 'KeqEqual' è usato solo per l'inserimento/ricerca e che' std :: unordered_set :: operator == 'verifica se due insiemi sono uguali in base i singoli elementi sono paragonabili? Potrebbe avere bisogno di un avvocato di lingua C++ qui. – dreamlax

risposta

2

"23.2.5 contenitori associativi non ordinate" afferma:

due ordinato contenitori ae b confronta uguale se a.size() == b.size() e, per ogni equivalente = gruppo di chiavi [Ea1, Ea2) ottenuto da a.equal_range (Ea1), esiste un gruppo di chiavi equivalenti [Eb1, Eb2) ottenuto da b.equal_range (Ea1), tale che distanza (Ea1, Ea2) == distanza (Eb1, Eb2) e is_permutation (Ea1, Ea2, Eb1) restituisce true.

spellatura questo giù, tutto si riduce a parità di contenitori non ordinate essendo definito in termini di std::is_permutation().

La parte importante è che questo fa riferimento alla forma a tre argomenti di std::is_permutation() e non alla forma a quattro argomenti!

In altre parole, l'intero castello di carte finisce per essere ridotto al valore predefinito operator==, per il contenuto del contenitore non ordinato, piuttosto che alla funzione di confronto ufficiale del contenitore.

Questa è la mia lettura su questo.

3

Secondo http://en.cppreference.com/w/cpp/container/unordered_set/operator_cmp avete infatti bisogno del operator== per il confronto (non ho accesso allo standard in questo momento - cercherò di aggiornare il specifica citazione domani):

Il comportamento non è definito se la chiave non è EqualityComparable.

Il comportamento è anche indefinito se Hash e KeyEqual non hanno lo stesso comportamento sulla sx e dx o se l'operatore di confronto di uguaglianza Key non è un perfezionamento della partizione in equivalente-chiave gruppi introdotte dal KeyEqual (cioè, se due chiavi che risultano uguali caduta in partizioni diverse)

Problemi correlati