Newsgroup: it.comp.lang.c++
Titolo: oggetti in map<> e queue<>: operator<

ciao  a tutti, ho avuto la necessita' di utilizzare dei contenitori
map<Obj,...> e priority_queue<Obj> dove Obj e' una classe da me creata.
Dovevo quindi implementare operator< per la mia classe.
A questo punto e' sorto il problema di come implementare tale operatore,
in quanto nella priority_queue<> dovevo (ovviamente) ordinarli secondo una
priorita';
ad esempio:
bool operator<(const Obj& dx) const{
    return this->priority < dx.priority;
}
questo modo pero' non va bene per implementare operator< per le map,
che in tal modo "sovrascriverebbero" sempre tutti gli oggetti Obj con
priorita'
uguale.
il bruttissimo modo che ho trovato e' di definire due classi Obj1 e Obj2
che differiscono solo per operator<.
Sbaglio qualcosa? o, se non sbaglio, c'e' un altro modo di fare questa cosa?
grazie!
--
Ciao by Allanon

 cosa?
Uno degli argomenti delle classi template map<> e priority_queue<> serve
esattamente a specificare il criterio di confronto degli elementi. Tale
argomento ha un valore di default che è rispettivamente less<Key> e less<
typename Container::value_type>. Puoi però definire due separate classi
funzionali che implementino i due diversi criteri di confronto e
adoperarle per instanziare i due container template.
Più semplicemente, potresti definire operator< di Obj in modo che funzioni
correttamente con map<> e creare una sola classe funzionale da usare con
priority_queue<>:
  struct prio_comp {
    bool operator()( const Obj& lh, const Obj& rh ) const
    {  
      // assumiamo per semplicità che prio_comp sia friend di Obj
       return lh.priority < rh.priority; 
    }
   }; 
  typedef priority_queue< Qbj, prio_cmp >  Obj_prio_queue_type;
Max

 che differiscono solo per operator<.
Un metodo migliore potrebbe essere quello di definire un'unica classe di
comparazione con l'overload del metodo
operator < (...), se possibile. Oppure un 'unico operator < (...) ed un
metodo di set, in modo che ordini in un modo od in un'altro a seconda di
quello che serve. Per far ciò basta un'unsigned int da poter valutare con lo
switch.
Se, invece la tua necessità è quella di dover ordinare i tuoi oggetti con
due metodi diversi...Ad esempio ai estratto dei dati da un db e vuoi
ordinarli prima per data, e poi per tipo di dato, allora deivi prima usare
la sort e poi la stable_sort.
Spero i averti aiutato.

 questo modo pero' non va bene per implementare operator< per le map,
Puoi, dichiarando i tuoi oggetti di tipo map e priority_queue,
specificare nella dichiarazione la funzione usata per i confronti.
Quindi non e' necessario usare lo stesso metodo per entrambi i
contenitori.
-- 
Maurizio Loreti                         
http://www.pd.infn.it/~loreti/mlo.html
Dept. of Physics, Univ. of Padova, Italy          loreti at pd dot infn dot it

 priority_queue<>:
[cut]
grazie a tutti, avevo letto qualcosa di questa per me "occulta"
caratteristica, ma non mi ero mai informato piu' di tanto...
volo a provare!
--
Ciao by Beppe

 prima usare la sort e poi la stable_sort.
questa complicazione del doppio sort non e` necessaria. Ecco un esempio 
di ordinamento prima per data e poi per tipo di dato:
class DBObject {
        date d;
        datatype dt;
        friend class OrderByDate_Datatype;
public:
        ...
};
class OrderByDate_Datatype {
public:
        bool operator()(DBObject a, DBObject b)
        {
                if( a.d == b.d ) return a.dt < b.dt;
                return a.d < b.d;
        }
};
DBObject v[10];
...
std::sort(v, v+10, OrderByDate_Datatype() );
ciao Anto
-- 
Antonio Cuni, 20 anni, studente
Brainbench C++ Master: 4.73, higher than 99% of all previous test takers.
C Language: 3.79, higher than 92% of all previous test takers.
Guida C/C++ di Programmazione.it: 
http://cpp.programmazione.it

 di ordinamento prima per data e poi per tipo di dato...
io preferisco una soluzione di questo tipo:
// CMisura: classe che gestisce le misure
typedef deque<CMisura *> LISTAMISUREIND;
// Lista delle misure
LISTAMISUREIND listaMisure;
// OrdinaMisure classe che mi gestisce l'ordinamento delle misure
// in funzione di vari metodi.
// Ordino in funzione del nome della misura
OrdinaMisure ordina(OrdinaMisure::IDPARAMETRO);
std::sort(listaMisure.begin(), listaMisure.end(), ordina);
// Cambio la chiave di ordinamento
// Ordino in modo crescente la data di registrazione della misura
ordina.SetDirezione(OrdinaMisure::CRESCENTE, OrdinaMisure::DATAREG);
std::sort (listaMisure.begin(), listaMisure.end(), ordina);
Dove OrdinaMisure è una classe che uso non solo per la sort, ma che posso
usare anche per le ricerche binarie definite dalla STL, bast aggiungere
l'overload degli operatori necessari, inoltre ho incapsulato i metodi di
ordinamento, che non è una brutta cosa, anche se questa classe è
specializzata solo per i puntatori a CMisura.
Ciao, Maurizio