2010-06-09 5 views
13

Ho una classe con un paio di campi numerici, quali:operatore Implementazione <in C++

class Class1 { 
    int a; 
    int b; 
    int c; 
public: 
    // constructor and so on... 
    bool operator<(const Class1& other) const; 
}; 

ho bisogno di usare oggetti di questa classe come una chiave in una std::map. Pertanto attuo operator<. Qual è l'implementazione più semplice di operator< da utilizzare qui?

EDIT: Il significato di < può essere assunto in modo da garantire l'unicità fintanto che uno qualsiasi dei campi non sono uguali.

EDIT 2:

A semplicistica implementazione:

bool Class1::operator<(const Class1& other) const { 
    if(a < other.a) return true; 
    if(a > other.a) return false; 

    if(b < other.b) return true; 
    if(b > other.b) return false; 

    if(c < other.c) return true; 
    if(c > other.c) return false; 

    return false; 
} 

Tutta la ragione di questo post è solo che ho trovato quanto sopra implementazione troppo prolisso. Dovrebbe esserci qualcosa di più semplice.

+0

È necessario innanzitutto decidere quali '<' significa per il caso in cui più membri rappresentano l'invariante della classe. –

risposta

4

Dipende se l'ordine è importante per te in qualsiasi modo. In caso contrario, si può solo fare questo:

bool operator<(const Class1& other) const 
{ 
    if(a == other.a) 
    { 
     if(b == other.b) 
     { 
      return c < other.c; 
     } 
     else 
     { 
      return b < other.b; 
     } 
    } 
    else 
    { 
     return a < other.a; 
    } 
} 
+0

Grazie !! Questo è quello che stavo cercando. –

+0

Oppure, per divertimento, 'return a! = Other.a? A Skizz

+8

Non vedo in che modo questo è meglio della "semplicistica implementazione" che l'OP ha dato. Questa versione è meno leggibile. – Frank

28

Suppongo che vogliate implementare l'ordinamento lessicografico.

#include <boost/tuple/tuple.hpp> 
#include <boost/tuple/tuple_comparison.hpp> 
bool Class1::operator<(const Class1& other) const 
{ 
    return boost::tie(a, b, c) < boost::tie(other.a, other.b, other.c); 
} 
+0

Bello! Ma la spinta è troppo pesante per il mio caso particolare. –

+0

Fantastico, non ho mai pensato di usare le tuple! –

+1

@Agnel Kurian: non c'è bisogno di "usarlo" oltre questo legame. È anche solo intestazione, per minimizzare l'impatto di build (tempo/dipendenze) è possibile isolarlo in una unità di compilazione separata (ma per build di release, prendi in considerazione l'intestazione per l'inlining!) – sehe

-4

Si potrebbe fare:

return memcmp (this, &other, sizeof *this) < 0; 

ma che ha un sacco di di avvertimenti - non vtbl per esempio, e molto altro sono sicuro.

+4

Quasi mai funzionerà come previsto. –

+0

@Peter: l'OP vuole solo che "garantisca l'unicità fino a quando uno dei campi non è uguale", quindi, aggiungendo uno scostamento per ottenere l'indirizzo del primo campo chiave e assicurandosi che i campi chiave siano contigui, memcmp dovrebbe fare il trucco . – Skizz

15

penso che ci sia un equivoco su ciò che map richiede.

map non richiede che la classe abbia il valore operator< definito. Richiede un predicato di confronto adatto da passare, che per impostazione predefinita è std::less<Key> che utilizza operator< su Key.

Non è necessario implementare operator< per inserire la chiave nello map. Dovresti implementarlo solo se lo definisci per questa classe: cioè se è significativo.

Si potrebbe perfettamente definire un predicato:

struct Compare: std::binary_function<Key,Key,bool> 
{ 
    bool operator()(const Key& lhs, const Key& rhs) const { ... } 
}; 

E poi:

typedef std::map<Key,Value,Compare> my_map_t;