Newsgroup: it.comp.lang.c++
Titolo: Riunire 3 funzioni quasi identiche in una

Ciao a tutti!
nel mio codice ho tre funzioni identiche, tranne che per una sola riga.
In questa riga, viene calcolato il valore di una variabile unsigned, ma in 
ciascuna delle tre funzioni viene calcolato usando una formula diversa.
In pratica:
Funzione1(parametri) {
...
unsigned Data = Formula1;
...
}
Funzione2(parametri) {
...
unsigned Data = Formula2;
...
}
Funzione3(parametri) {
...
unsigned Data = Formula3;
...
}
Vorrei sapere se esiste un modo elegante per avere una sola funzione invece 
di 3, nella quale Data viene calcolato secondo Formula1, Formula2 o Formula3 
a seconda del caso.
Naturalmente basterebbe inserire un un paio di if parametrizzati su un 
valore passato tra i parametri, ma dal momento che ad ogni chiamata di 
Funzione, Data viene calcolato da un minimo di 4 a un massimo di 32 volte, e 
che ciascuna delle 3 Funzioni viene richiamata molte migliaia di volte, la 
cosa potrebbe risultare poco performante. Si tratta di una elaborazione su 
immagini, per cui la performance è fondamentale.
Grazie Ciao! 

 a seconda del caso.
tralasciando il caso, sicuramente motivato, per cui non passi il 
dato dall'esterno già calcolato, avrai le tue ragioni ...
cmq si, esiste, e consiste nei puntatori a funzione. Da dentro 
un'unica funzione calcoli data attraverso un puntatore a funzione
Puoi usare sia il passaggio dell'indirizzo della funzione come 
parametro
FunzioneComunq(parametri, unsigned (* FormulaEnne) (parametri 
formali)) {
unsigned Data = (* FormulaEnne) (dati attuali);
// dove cavolo li prende i dati attuali ? Non si sa senza 
ulteriori specifiche
}
Oppure puoi creare un array di puntatori statico, interno allo 
scope più ristretto che include la funzione, inizializzarlo con 
puntatori alle varie funzioni di calcolo, e passare come 
parametro soltanto un INDICE
tpedef unsigned (* PtrFormulaEnne) (parametri formali);
static PtrFormulaEnne [3] = {& Formula1, & Formula2, & Formula3}
FunzioneComunq(parametri, unsigned Indice) {
unsigned Data = (* PtrFormulaEnne [Indice]) (dati attuali);
// dove cavolo li prende i dati attuali ? Non si sa senza 
ulteriori specifiche
}
rimane il problema di come passare i dati se la funzione 
parametrica ne richiede .... potresti aggiungerli alla lista di 
parametri più esterni
Se invece ciascuna formula ha parametri differenti, nel 
prototipo di esse, e così pure di quella che le usa, non hai 
altro modo che dichiarare l'ellissi (...), e la cosa si fa scomoda.
ciao
Soviet



Grazie! Sicuramente entrambe le soluzioni sono valide.
Le tre formule di calcolo per Data usano tutte gli stessi parametri, che 
sono presenti nella funzione in cui si calcola Data.
Un'ultima domanda, per ragioni di performance, vorrei evitare la chiamata 
alla funzione. potrei dichiarare le tre funzoni come inline?
grazie Danilo 

 alla funzione. potrei dichiarare le tre funzoni come inline?
Hai detto che è una funzione che viene chiamata moltissime volte
all'interno del programma. Pensa che se le dichiari inline,  
avrai nel binario del programma N copie della funzione,
per quante sono le volte che la funzione viene chiamata. Ciò, quando la
funzione esegue operazioni non banalissime, può essere un problema
invece che un vantaggio.
Ciao
-- 
Salvatore

 invece che un vantaggio.
In realtà c'è una copia del codice della funzione *per ogni punto di 
chiamata* della stessa e non ad ogni chiamata. La cosa è molto diversa. Ad 
esempio, in un loop da 1000 iterazioni con dentro una chiamata a quella 
funzione ce ne sarà solo una copia non 1000.
EMG
--
EMAG Software Homepage:     
http://www.emagsoftware.it
The EMG's ZX-Spectrum Page: 
http://www.emagsoftware.it/spectrum
The Best of Spectrum Games: 
http://www.emagsoftware.it/tbosg
The EMG Music page:         
http://www.emagsoftware.it/emgmusic
 

 wrote in message 
news:uc6Oi.113$tt3...@nntpserver.swip.net...


 alla funzione. potrei dichiarare le tre funzoni come inline?
Non servirebbe a niente perchè per espandere la funzione inline il 
compilatore dovrebbe sapere quale e' la funzione chiamata. 
Un'alternativa efficiente sarebbe usare un template parametrizzato con 
la funzione da chiamare (non sono sicuro, ma penso si possa fare).
E.

 }
template <int i>
funzione(parametri)
{
   unsigned Data = (i == 1) ?
                     Formula1 :
                   (i == 2) ?
                     Formula2 :
                   Formula3;
   ...
}
Kiuhnm

 con la funzione da chiamare (non sono sicuro, ma penso si possa fare).
Stavo per scrivere la stssa cosa... credo comunque che un buon
compilatore possa decidere (se lo ritiene opportuno) di mettere inline
la funzione esterna, ovvero di farne tre versioni ciascuna con un
puntatore diverso(comportandosi all'atto pratico come il template).
--
Marco
 
-- 
I'm using an evaluation license of nemo since 49 days.
You should really try it!
http://www.malcom-mac.com/nemo

 Kiuhnm
Ciao! Questa sintassi č davvero interessante. Domanda: Dal momento che il 
template viene valutato all'atto della compilazione, la parte in cui si 
decide quale Forumula usare viene eseguita a runtime oppure no?
Grazie! 

 decide quale Forumula usare viene eseguita a runtime oppure no?
L'uso di ?: non è importante. Qualsiasi compilatore ottimizzante che si 
rispetti elimina salti condizionali la cui condizione è costante e 
conosciuta a compile time.
Kiuhnm

Kiuhnm ha scritto:
però questo approccio è applicabile solo se il valore numerico 
con cui si seleziona la funzione appropriata è risolto a literal 
costante a COMPILE TIME, non è adatto se la selezione avviene 
con indice variabile a run time ...
non avevo capito dalla domanda iniziale che il valore fosse noto 
nel codice come una costante
ciao
soviet_mario


 a run time ...
In tal caso devi usare codice automodificante. Non si scappa.
Kiuhnm

 TIME, non č adatto se la selezione avviene con indice variabile a run time 


 performance (utilizzo VC++ 2005)
Lascia perdere il profiler, almeno per il momento, e guarda l'asm.
Metti un break point a inizio funzione, esegui il programma e, dopo il 
break, premi alt+8. I salti hanno la forma jmp o jx address.
Comunque, ripeto, l'uso di ?: è totalmente arbitrario. Puoi anche usare 
if, switch, ecc...
Do per scontato che tu stia parlando della versione release...
Kiuhnm

Kiuhnm ha scritto:

Può anche usare la funzione stessa come parametro del template
template <unsigned fz_calc(parametri)>
tipo_di_ritorno funzione(parametri)
{
   ...
   unsigned val = fz_calc(xx);
   ...
}
quindi
result = Funzione<Formula1>(parametri);
Ciao

  {
[...]
Su questa sintassi non sono convinto, ma credo anch'io sia possibile
passare direttamente la funzione e non sia necessario
l'if/switch...Questo se le tre funzioni hanno prototipo comune,
altrimenti rimane
la soluzione con if/switch
--*PaN!*
 
-- 
I'm using an evaluation license of nemo since 50 days.


 la soluzione con if/switch
Oppure si passa una classe.
Kiuhnm

 Può anche usare la funzione stessa come parametro del template
FANTASTICO (... se funge :-).
A parte gli scherzi, mi sembra elegantissimo e sintetico. Non 
avevo mai pensato che tra i typename ci potesse stare anche una 
funzione. A volte ho un po' i paraocchi.
Se funge, fare un template con un typedef diventa anche 
grammaticalmente agile.
ciao
Soviet


 FANTASTICO (... se funge :-).
Io però l'avevo suggerito già due giorni fa! Voglio anch'io una parte 
dei complimenti! ;-)
E.

 wrote in message 
news:sEEOi.1007$ga5...@tornado.fastwebnet.it...


 E.

 E.

 dei complimenti! ;-)
Kudos!
-- 
blog:  
http://www.akropolix.net/rik0/blogs
 | Uccidete i filosofi,
site:  
http://www.akropolix.net/rik0/
      | tenetevi riso e
forum: 
http://www.akropolix.net/forum/
     | bacchette per voi.