Ho una classe C++ per la quale ho bisogno di definire un comparatore che dovrebbe considerare il risultato di diversi metodi potenzialmente costosi. Non voglio memorizzare nel cache il risultato di questi metodi per tutti gli oggetti nel mio set, perché i criteri con la priorità più alta sono più economici, e mi aspetto che quelli molto costosi in basso si attivino solo in rari casi.Confronto C++ profondo e pigro con sintassi elegante?
Se avessi una funzione cmp() restituita rispettivamente -1, 0 o 1 quando il primo argomento è minore, uguale o superiore al secondo e con gli operatori logici di scelta rapida che conservano gli interi, potrei scrivere facilmente
int compare(const Class &rhs) const {
return cmp(expensive_method_a(), rhs.expensive_method_b()) ||
cmp(expensive_method_b(), rhs.expensive_method_b()) ||
...
}
Purtroppo ho bisogno di lavorare con l'operatore <, così diventa brutto, costoso e soggetto a errori:
bool operator<(const Class &rhs) const {
return expensive_method_a() < rhs.expensive_method_a() ||
(expensive_method_a() == rhs.expensive_method_a() &&
(expensive_method_b() < rhs.expensive_method_b() ||
(expensive_method_b() == rhs.expensive_method_b() &&
(...
))))
}
Oppure, in alternativa, meno costoso ma ancora piuttosto brutta:
bool operator<(const Class &rhs) const {
auto al = expensive_method_a(), ar = rhs.expensive_method_a();
if (al != ar) return al < ar;
auto bl = expensive_method_b(), br = rhs.expensive_method_b();
if (bl != br) return bl < br;
Ho letto su std :: tie a This altra domanda, ma se ho capito bene, la cravatta valuterà tutti i miei metodi prima di iniziare il confronto, e voglio che questi argomenti siano pigramente valutati.
ho pensato sulla definizione di un macro preprocessore come questa:
#define CUT_COMPARE(a,b) { auto _x = (a); auto _y = (b); if (_x != _y) return (_x < _y); }
che avrei usato come:
bool operator<(const Class &rhs) const {
CUT_COMPARE(expensive_method_a(), rhs.expensive_method_a());
CUT_COMPARE(expensive_method_b(), rhs.expensive_method_b());
...
}
sperando che le parentesi graffe avrebbero racchiudere la mia _x
e _y
in un ambito privato, ma ahimè, clang++
si lamenta di più definizioni di _x
e _y
.
C'è un modo più carino per aggirare questo?
Perché il clang si lamenta? Non ho testato il codice, ma sembra che le variabili siano in ambiti separati. –
Proprio come una nota, 'CUT_COMPARE' dovrebbe in effetti essere scritto' #define CUT_COMPARE (a, b) do {....} while (0) 'per i motivi trovati qui: http://stackoverflow.com/questions/ 1067226/c-multi-line-macro-do-while0-vs-scope-block –