Newsgroup: it.comp.lang.c++
Titolo: problemi con la STL

Ciao a tutti!
Sono alle primissime armi con l'utilizzo del linguaggio C++, in passato ho
avuto qualche esperienza di programmazione in C.
Vorrei che qualcuno mi illuminasse su questo piccolo problema.
Ho creato una classe "sfera":
class sfera
{
  public:
  float x,y,z,R;
}
( ..più che una classe, per ora è ancora una struttura......)
dove x,y,z sono le coordinate del centro della sfera mentre R è il raggio.
Tramite la STL ho poi creato una lista di oggetti tipo sfera(letti da un
file di testo) chiamata "listasfere"
Vorrei ordinare questa lista mettendo le sfere in ordine di raggio
decrescente, da quella di raggio massimo a quella di raggio minimo; per
farlo, voglio sfruttare la funzione membro void sort( ).....e fare qualcosa
del tipo
listasfere.sort( );
come faccio ad indicare al mio programma che il sorting va effettuato sul
quarto parametro, cioè sul raggio R??
Ho letto che dovrei creare una funzione template di confronto e passare
questa funzione al comando sort, ma non ci sono riuscito....ho qualche
problema con la sintassi.
Qualcuno può aiutarmi???
Grazie , Fabio

 decrescente, da quella di raggio massimo a quella di raggio minimo;
prova qualcosa del genere...
class pesasfere  {
public:
  operator() (const sfera &fst, const sfera &snd) {
    return fst.R < snd.R;
  }
};
e, per utilizzarlo,
listasfere l;
l.sort(pesasfere());
buona fortuna (fammi sapere se andava),
    rony.
--
-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
"Solo due cose sono infinite,
l'universo e la stupidita' umana,
e non sono sicuro della prima."
Albert Einstein

 l.sort(pesasfere());
mmm, un valore di ritorno per pesasfere() no ?
e poi non era più semplice usare una funzione ?
Massimo

 };
mi sa che e' meglio
class sfera  {
//...
public:
   operator <(const sfera &s) {
     return ( R < s.R);
   }
   operator ==(const sfera &s) {
     return ( R == s.R);
   }
};
set<sfera> listasfere;
l'ordinamento e' automatico ad ogni inserzione, ed eviti sfere doppie.
se poi ti servono i doppioni, usa multiset.

 l'ordinamento e' automatico ad ogni inserzione, ed eviti sfere doppie.
Ed evitare sfere doppie è sempre bene... ;-)
Massimo

Il giorno Fri, 09 Feb 2001 19:26:00 GMT, "Sandro" ha digitato quanto 
segue:
emmm, mancano i const bool davanti ai due operator... va be', si 
capiva, no?-)

capiva, no?-)
Forse intendi i "bool" prima e i "const" dopo la chiusa
tonda... "const bool" come valore di ritorno non
ha molto senso
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

 ha molto senso
dopo le 10, non sono + affidabile: il cervello e' spento...
quello che dici è perfettamente sensato.

convengo con voi che la soluzione del set sia più elegante ;)
certo, il nome è un po' fuorviante... dal punto di vista teorico una lista e
un insieme sono cose ben diverse!


    }
Se non sbaglio il confronto per uguaglianza e' superfluo, perche' l'STL
usa !(A<B||B<A)
Ciao,
Nicola

usa !(A<B||B<A)
non c'è modo per imporgli un metodo di uguaglianza definito da me? nel
caso operator<() fosse molto dispendioso e operator==() molto veloce
sarebbe uno spreco usare il primo per verificare l'uguaglianza.
Anto
--
Antonio Cuni, 18 anni, studente
Brainbench Certification: 
Master C++: 4.44, higher than 97% of all previous test takers.
Visual Basic 5: 3.06, higher than 77% of all previous test takers.
http://www.brainbench.com/transcript.jsp?pid=1301688

A dire il vero con certezza non lo so. Bisognerebbe spulciare la
documentazione STL o lo standard...
Ciao,
Nicola

 documentazione STL o lo standard...
per la precedenza dei tipi utente, dovrebbe usare il tuo, comunque. 

 sarebbe uno spreco usare il primo per verificare l'uguaglianza.
Per chiarificare: dipende :-)
Non _tutta_ la STL converte [uguale] in [non minore e non maggiore];
esistono alcuni metodi di programmazione generica (in <algorithm>,
tipo std::sort) ed alcuni containers (tipo std::set) che richiedono un
ordinamento (piu' esattemente, uno strict weak ordering).  Per _quei_
metodi o oggetti bisogna o fornire un operator < (se non esiste di
default) o un function object di paragone che sia equivalente ad
operator <.
-- 
Maurizio Loreti                         
http://www.pd.infn.it/~loreti/mlo.html
Univ. of Padova, Dept. of Physics - Padova, Italy            
lor...@pd.infn.it
The instructions said to use Windows 98 or better - so I installed FreeBSD.

documentazione STL o lo standard...
sono andato a cercare sullo Stroustrup (17.1.4.2); a quanto sembra non
si puņ: le motivazioni sono che operator==() non č usato molto di
frequente nella STL e che nel 50% dei casi č necessaria una sola
chiamata a operator<(); cmq mi sembra una limitazione: pensate un po'
se operator< avesse un tempo O(n*n) e operator== un tempo O(1)...


 se operator< avesse un tempo O(n*n) e operator== un tempo O(1)...
Non mi sembra molto realistico, dato che per numeri semplici le due
operazioni sostanzialmente si equivalgono e la maggior parte delle
implementazioni su classi complesse si limitano ad applicare le stesse
operazioni su tipi nativi in modo iterativo con un certo ordine.
Ciao,
Nicola

 se operator< avesse un tempo O(n*n) e operator== un tempo O(1)...
Non credo che sia molto realistico che un operator == sia O(1) e il relativo
operator < sia O(n*n). Dico relativo perche' ovviamente se i due operatori fanno
cose completamente diverse la cosa e' possibile.
Inoltre nella STL questi operatori sono usati in maniera abbastanza matematica.
Ovvero: laddove l'algoritmo ha bisogno solamente di una uguaglianza si usa solo
l'operator ==. Laddove l'algoritmo si basa su una funzione d'ordine stretto e
totale (come per il sort o la ricerca binaria) si usa solo operator <. Questi
algoritmi possono essere implementati in maniera piu' efficiente (e con una
interfacccia piu' semplice) senza usare l'operator == (che comunque verrebbe
usato al massimo una volta).
Esempio e' il caso della ricerca dicotomica in una sequenza ordinata secondo
operator<. La ricerca non da come risultato un r tale che r==s dove s e' il
valore cercato. Per farlo dovrebbe prevedere un valore di ritorno misto o
multiplo (potrebbe non esserci tale valore). Pertanto viene semplicemente
restituito l'iterator corrispondente al primo (dall'inizio della sequenza)
elemento r tale che !(r<s). E questo viene fatto comunque usando solo operator<.
Il test finale con l'operator== e' lasciato a te.
Andrea Ferro
---------
Brainbench C++ Master. Scored higher than 97% of previous takers
Scores: Overall 4.46, Conceptual 5.0, Problem-Solving 5.0
More info 
http://www.brainbench.com/transcript.jsp?pid=2522556

cose completamente diverse la cosa e' possibile.
si hai ragione, il mio era un ragionamento al limite. Cmq, anche se
probabilmente non ne avrò mai bisogno, continuo a percepire come una
limitazione questo fatto: forse mi sbaglio, ma sarebbe stato
necessario un solo parametro facoltativo al template.


 necessario un solo parametro facoltativo al template.
Quale template? Mi pare che tutti i template della STL prendano un solo
parametro per la comparazione. Quale mi e' sfuggito?


parametro per la comparazione. Quale mi e' sfuggito?
quello che non c'è ;-)
oltre a un parametro per la comparazione potrebbero prenderne anche
uno per l'uguaglianza, magari in modo che per default utilizzi il
primo nella forma !operator<(a,b) && !operator<(b,a)


 primo nella forma !operator<(a,b) && !operator<(b,a)
Mi sta sfuggendo una cosa: quale template della libreria standard, per te, usa
operator< per costruirsi operator== ?
Non dico che qualche implementazione particolare non lo faccia. Ma non mi sembra
che esista un solo algoritmo (e non intendo solo i template dell'header
<algorithm> ma anche gli algoritmi specifici delle varie classi) che richieda
l'uso di operator== e che non ne preveda la specificazione.
La cosa piu' vicina a fare quello che dici tu che mi viene in mente e' la logica
con cui un container associativo considera un oggetto da inserire uguale ad un
oggetto gia' inserito. Ma in questo caso le due chiamate a operator< (che devono
entrambe rirornare falso) avvengono in due momenti diversi e, praticamente,
avverrebbero comunque, pertanto l'introduzione di operator== sarebbe ridondante.


operator< per costruirsi operator== ?
guarda che il thread č cominciato proprio da lě...
i contenitori standard non richiedano che l'oggetto contenuto
implementi operator==(). Se devono fare una uguaglianza si basano su
operator<(), o sul predicato che gli č stato passato. cfr Stroustrup,
paragrafo 17.1.4.2


 paragrafo 17.1.4.2
Non ho lo Stroustrup, ma non mi risulta che i contenitori abbiano mai bisogno di
verificare una uguaglianza in maniera ripetitiva. L'unico caso che mi viene in
mente e' l'"uguaglianza" dell'oggetto da inserire/rimuovere nei container
associativi, ma in questo caso vengono fatti mediamente log(n) test con
operator< e al termine ho l'oggetto contenuto "o" e l'oggetto da inserire "n" e
ho gia' eseguito il test o<n (oppure n<o a seconda dell'implementazione) e devo
solo verificare se sono uguali. Dato che SO GIA' il risultato di uno dei
paragoni, la scelta e' fra: richiedere che venga specificato anche un operator==
(che invochero' una sola volta) e eseguire il test con gli operandi invertiti
(una sola volta in piu' rispetto a quelle che comunque ho gia' fatto).
Considerando l'aumento della complessita' dell'interfaccia e il problema di
garantire che l'operator== dia risultati consistenti con l'operator< mi sembra
logica la scelta fatta!
In tutti i casi in cui serve un test di equivalenza ripetitivo (come nelle
ricerche sequenziali) viene usato l'operator== e NON l'operator< due volte.
O mi sono perso qualche cosa?


O mi sono perso qualche cosa?
forse sono io che ho interpretato male il testo di Stroustrup. Se non
viene precisato alcun predicato di confronto viene usato operator==().
Quindi il problema si pone solo quando passo al template il mio
predicato cmp. Ti riporto testualmente l'esempio di Stroustrup:
if (x==y) // eseguito quando l'utente non fornisce un confronto
if (!cmp(x,y) && !cmp(y,x)) /* eseguito quando l'utente fornisce un
	confronto cmp */
Resto cmq della mia idea. Non vedo quale complicazione all'utilizzo
avrebbe portato una cosa del genere:
template<class T, class less_cmp, class equal_cmp> class vector;
Anto
--
Antonio Cuni, 18 anni, studente
Brainbench Certification: 
Master C++: 4.6, higher than 98% of all previous test takers.


 template<class T, class less_cmp, class equal_cmp> class vector;
Il tamplate vector non richiede la presenza di nessunissimo tipo di comparatore
e non esegue nessunussimo tipo di comparazione. Non usa operator==, non usa
operator<, non usa nessun "cmp" definito dall'utente! Qundi non ha senso
inserire i parametri less_cmp e equal_cmp nel template vector (che comunque
dovrebbero avere un default, e hai dimenticato l'allocator).


dovrebbero avere un default, e hai dimenticato l'allocator).
hai ragione, ho usato l'esempio meno calzante :-((
