Newsgroup: it.comp.lang.c++
Titolo: errore che non capisco

sto lavorando con il template priority_queue, di default è ordinata in senso
discendente, io la voglio ordinata in senso ascendente, per far questo ho
eseguito l'overload di push e pop. inoltre gli elementi della coda sono di
tipo MiaClasse in cui ho definito anche l'overload dell'operatore >
(maggiore di):
class MiaClasse
{
public:
    ...
    bool operator > (const MiaClasse Elem2);
};
template <class T>
class cCodaPrior : public std::priority_queue <T>
{
public:
    typedef greater <MiaClasse> Pred;
    void push(const value_type& _X)
    {
         c.push_back(_X);
         push_heap(c.begin(),c.end(),compara);
    }
    void pop()
    {
         pop_heap(c.begin(),c.end(),compara);
        c.pop_back();
    }
protected:
    Pred compara;
};
in main ho una dichiarazione come segue:
cCodaPrior Coda
quando compilo mi dice che non è stato definito alcun operatore '>' che
prenda come operando destro un oggetto MiaClasse (questo operando serve per
ordinare la coda), insomma finchè la coda è di int o un altro tipo
predefinito va tutto bene (la coda è effettivamente ordinata in modo
ascendente), quando gli indico MiaClasse mi dà l'errore di cui sopra.
l'errore per la precisione è:
error C2678: binary '>' : no operator defined which takes a left-hand
operand of type 'const class cCella' (or there is no acceptable conversion)
Io mi domando: l'overload dell'operatore non lo vede? Ho sbagliato qualcosa?
Grazie e ciao
--
Roberto
FV
----------
rob...@messora.com
ICQ# 37732681
----------
Membro di SFI Italy
Simulazioni PBEM di Star Trek
 
http://gioco.net/startrek
(Crusader, Highlander, Unicorn)
----------
Resistance is futile

 class cCodaPrior : public std::priority_queue <T>
Dopo di che, perche' non passi alla priority_queue la funzione di
confronto invece di specializzarla (operazione sempre discutibile,
perche' nessun contenitore STL ha distruttore virtuale)?
Ciao,
Nicola

 perche' nessun contenitore STL ha distruttore virtuale)?
Non ho fatto altro che mettere il precedente const, non ho fatto quello che
poi mi hai detto (che fra l'altro non ho capito), ora funziona.
Se non ti č di impiccio mi spiegheresti perchč ora funziona? Onestamente il
const che ho inserito non lo capisco davvero.
E poi se per favore mi spieghi la frase sul passare alla pr_queue la
funzione di confronto: se tu l'avessi scritta in aramaico antico per me non
ci sarebbero state differenze :-)
Ciao


 ci sarebbero state differenze :-)
Il template priority_queue e' definito come 
priority_queue<T, Sequence, Compare>
dove T e' il tipo base, Sequence e' il contenitore da utilizzare come
base (di default e' vector<T>) e Compare e' l'oggetto funzionale da
utilizzare per il confronto (di default e' less<T>, ovvero la forma
templatizzata dell'operatore minore).
Questo significa che hai diverse opzioni per ridefinire l'ordinamento:
- Puoi ridefinire l'operatore minore per la tua classe;
- Puoi definire una specializzazione di less<T>;
- Puoi passare al costruttore un tuo oggetto funzionale che implementa
  il confronto.
La prima e' probabilmente l'opzione piu' semplice.
Se ti poni questo genere di problemi ti consiglio di procurarti un buon
libro sul C++ (o addirittura sulla libreria standard).
Ciao,
Nicola

 libro sul C++ (o addirittura sulla libreria standard).
Sto usando i template in quanto sto sviluppando un programma per la tesi,
programma che necessita di una matrice, una coda prioritaria e uno stack,
tutti dinamici in quanto non conosco a priori l'estensione del file di
ingresso che è il mio input (in pratica di tratta di una versione ritoccata
per le mie esigenze del famoso algoritmo di ricerca A* in cui si ha una
matrice di partenza, una coda prioritaria e uno stack, tale algoritmo
ricerca il cammino di minimo costo fra una locazione di partenza e una di
arrivo nelle matrice)
Mi sembra che utilizzare i template sia una soluzione elegante, non sono
costretto ad utilizzare puntatori esplicitamente per ricorrere alla memoria
heap (la coda prioritaria arriva in genere a contenere un numero di elementi
che si aggira sull'ordine di 400.000).
Il fatto è che la coda mi serve ordinata in maniera opposta a quella di
default.
Posso rubare ancora il tuo tempo?
Se si ti sottopongo questo altro quesito. Siccome la chiarezza del codice è
essenziale per me (appunto perchè farà èarte della tesi) ho la necessità di
tradurre in italiano il nome delle funzioni. L'unica cosa che mi è venuta in
mente è quella di avere delle funzioni membro delle mie classi template con
un identificativo italiano, funzioni che richiamano il corrispettivo inglese
(del tipo la funzione cCodaPior::Inserisci nel suo codice richiama soltanto
push). In pratica durante l'esecuzione mi si alloca memoria per la chiamata
intermedia di inserisci solo per poi chiamare push.
Esiste un modo mogliore?
Ciao e grazie ancora.


 Esiste un modo mogliore?
Nel caso specifico l'importante e' che le tue funzioni di istradamento
siano definite inline, ovvero o dentro la definizione della classe, o
sempre nel file di include, ma fuori dalla classe e con la parola chiave
inline anteposta alla definizione, ad es.:
inline int pippo::pluto() {}
In questo modo se il compilatore e' appena decente elimini il costo
della chiamata. Nota che se definisci inline funzioni complesse le
prestazioni potrebbero anche peggiorare invece di migliorare.
Ciao,
Nicola

 Ciao e grazie ancora.
template <class T> inline void cCodaPrior::Inserisci(T &elem)
{
    queue.push(elem);
}
L'inline dice al compilatore di fare quello che vuoi tu (evitare la chiamata
di funzione ed eseguire il codice direttamente), il template ti serve solo
se non sai a priori il tipo di oggetto da inserire nella coda, altrimenti
puoi specializzare la funzione.
Massimo
P.S.
Ovviamente i parametri e i valori di ritorno li ho messi a caso, non mi va
di andarmi a vedere la priority_queue ora ;-)


Non è questa la soluzione migliore.
La classe priority_queue è definita come:
  template <class T, class Container = vector<T>,
            class Compare = less<typename Container::value_type> >
  class priority_queue;
Di default priority_queue usa less<MiaClasse> per la comparazione
(ossia usa l'operatore < definito per MiaClasse).
Quindi basta che dichiari:
priority_queue< MiaClasse, std::vector<MiaClasse>,
                greater<MiaClasse> >.
Manlio Perillo

 Esiste un modo mogliore?
Le funzioni inline servono proprio a risolvere questo problema.
Manlio Perillo