2013-07-23 11 views
6

se ho già operatore> e operatore < definito (e operatore ==), ho bisogno di definire operatore> = e operatore < =, o sarà il compilatore li dichiarare per me se intenzionalmente non li dichiaro?Devo dichiarare manualmente> = e <= operatori?

Inoltre, se ho operatore == definito, sarà il compilatore dichiarare operatore! = per me?

+2

Se avere 'operator <' e 'operator ==' definito, è possibile trascinare nello spazio nomi ['std :: rel_ops'] (http://en.cppreference.com/w/cpp/utility/rel_ops/operator_cmp) per fornire il resto degli operatori, ma questa non è davvero una [buona soluzione] (http://stackoverflow.com/questions/62 25375/idiomatica-uso-di-stdrel-ops). [Boost.Operators] (http://stackoverflow.com/a/14756785/241631) è il modo giusto per farlo. – Praetorian

+0

Qualcosa non mi piace proprio usando l'ereditarietà per risparmiare la digitazione di alcuni operatori. Preferirei aggiungerli manualmente. =) –

+0

derivante da una classe che fornisce la funzionalità ha anche un grande valore di documentazione. È una forma primitiva di concetti. – TemplateRex

risposta

6

No, il compilatore non dichiarerà/definirà nessuno degli operatori che non hai definito manualmente. Tuttavia, Boost.Operators potrebbe essere di vostro gradimento - fa esattamente quello che volete che faccia il compilatore.

+0

Dang. Generano costruttori di copia predefiniti e simili. Speravo in un semplice operatore * generato automaticamente! = (Altro) {return! (* This == other); } *. Oh bene, grazie per la risposta!Aspetterò un po 'prima di accettarlo. –

+1

+1 il manutentore di Boost.Operators (Daniel Frey) ha una porta uofficial chiamata [df.operators] (https://github.com/d-frey/operators) di quella libreria a C++ 11 (sovraccarico di rvalue e noxcept) – TemplateRex

5

Il compilatore non farà nulla per sé per voi qui, ma è relativamente semplice per generare automaticamente ereditando dalla una classe adeguata, qualcosa di simile:

template< typename DerivedType > 
class ComparisonOperators 
{ 
public: 

    friend bool   operator!=( 
          DerivedType const& lhs, 
          DerivedType const& rhs) 
    { 
     return !(lhs == rhs); 
    } 

    friend bool   operator<=( 
          DerivedType const& lhs, 
          DerivedType const& rhs) 
    { 
     return !(rhs < lhs); 
    } 

    friend bool   operator>( 
          DerivedType const& lhs, 
          DerivedType const& rhs) 
    { 
     return rhs < lhs; 
    } 

    friend bool   operator>=( 
          DerivedType const& lhs, 
          DerivedType const& rhs) 
    { 
     return !(lhs < rhs); 
    } 

protected: 
         ~ComparisonOperators() {} 
} ; 

Definire < e == nella tua classe, e derivano da questo, e avrai tutti gli operatori:

class MyClass : public ComparisonOperators<MyClass> 
{ 
    // ... 
public: 
    bool operator==(MyClass const& other) const; 
    bool operator<(MyClass const& other) const; 
    // ... 
}; 

Solo una nota: ho semplificato manualmente la versione che ho Actu Al uso, che definisce == e < pure, cerca il membro funzioni compare e isEqual, e usa compare per == e != quando non c'è isEqual. Non credo di aver introdotto errori , ma non si sa mai.

+0

Preferisco un 'int compare (DerivedType const & o)' che restituisce un valore negativo, positivo o 0 (approccio C tradizionale). Di solito '==' e '<' sono codice molto simile quindi è bello fonderli. –

+3

Non è esattamente quello che fa Boost.Operators per te? ;-) –

+0

@ edA-qamort-ora-y Sì. Questa è la firma per 'compare', sopra. La regola è: solo confronti per l'uguaglianza: 'isEqual' (e gli operatori relazionali non riusciranno a compilare se vengono utilizzati); uguaglianza e relazionale, usare 'compare'; Se l'uguaglianza può essere fatta molto più velocemente, allora puoi fornire entrambi. E c'è un po 'di meta-programmazione nella classe 'ComparisonOperators' che chiamerà quella giusta. –

0

Qui ci sono già alcune buone risposte usando boost e l'ereditarietà. Ma come qualcuno ha notato - l'uso dell'ereditarietà per la creazione di un operatore sembra ... sbagliato.

Lo so #define s sono "taboo" in C++, ma è ancora quello che uso qui.

Ho un #define nella mia utilità generale comprendono che va come questo:

#define CREATE_COMPARITORS(name)        \ 
inline bool operator>(const name &o){return o<*this;}   \ 
inline bool operator<=(const name &o){return not (o<*this);} \ 
inline bool operator>=(const name &o){return not (*this<o);} \ 
inline bool operator!=(const name &o){return not (*this==o);} 

Poi se ho una classe, tutto quello che ho bisogno di dichiarare è operator< e operator==:

class ttt{ 
    //... 
    bool operator<(const ttt &o); 
    bool operator==(const ttt &o); 
    CREATE_COMPARITORS(ttt); 
    //... 
}; 
+0

Potrebbe essere necessario giustificare che "sembra ... sbagliato." A partire da ora mi fido dei designer di librerie di boost più che della tua opinione ingiustificata. – djechlin

+0

Stavo citando qualcun altro in questa discussione che diceva "Qualcosa non si adatta proprio a me usando l'ereditarietà per risparmiare la digitazione di pochi operatori". Ora, se vuoi mandarmi in meno di me perché la mia risposta non è stata utile o non hai aggiunto nulla, allora va bene. Ma se mi sottovaluti solo perché sono uno di un grande gruppo di persone a cui non piace "Boost" e come funziona, mentre tu fai parte di un altro gruppo che piace "Boost", allora sei abusare del tuo potere. – rabensky

+0

-1 per raccomandare l'uso di #define sull'ereditarietà, senza giustificazione per ciò che è sbagliato nell'ereditarietà o perché questo codice è esente dai soliti problemi con le macro. – djechlin

Problemi correlati