|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Jan 2000
Messaggi: 551
|
STL: Farsi un fuctor iota sofisticato(Cionci ,Marco invited)
Mi sono accorto che la STL non ha nello standard il comodo functor iota implementato dalla SGI
(serve a generare sequenze di numeri in container tipo vector,list etc) quindi me ne sono fatto uno a mano.(Puo darsi che nella libreria boost ci sia già, ma sulla macchina di mio fratello non l'avevo a disposizione). Non esitate a proporre miglioramenti o segnalare anomalie (ve ne sarei grato) Codice:
template <class T>
class iota_gen {
public:
iota_gen(T start,T increment) : current(start) ,inc(increment) {}
T operator () () {T tmp= current;
current+=inc;
return tmp ;}
private:
T current;
T inc;
};
//Esempio di chiamata
...
vector <double> viota(10);
//riempie viota a partire da 0.0 aggiungendo 1.5 al precedente elemento
generate(viota.begin(),viota.end(), iota_gen<double>(0.0,1.5));
...
(sottrazione,moltiplicazione,etc)per scegliere il modo in cui generare la sequenza e non limitarlo all'addizione. Siete capaci di farlo?Io al momento no. Non è un fatto necessario per me (al momento) ,ma mi sembrava un quesito interessante. Un esempio d'uso? suponete di avere la funzione x=f(y) non invertibile (o anche non facilmente invertibile). Voi avete bisogno invece di calcolare y=f(x) in un certo intervallo Xa -Xb . Un modo semplice è quello di approssimare y=f(x) con una poligonale. Quindi generate un vettore di n coordinate yi a partire da Ya con un intervallo (Ya-Yb)/(n-1); un altro vettore di n coordinate xi=f(yi). A questo punto potete calcolare qualunque valore Yc(Xc) sfruttando i punti a disposizione. Questo è il caso reale che è capitato a me |
|
|
|
|
|
#2 | |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Re: STL: Farsi un fuctor iota sofisticato(Cionci ,Marco invi
Quote:
Codice:
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
template <class T>
class iota_gen {
public:
iota_gen(T start,T increment, T (*oper)(T cur, T inc) = default_op)
: current(start) ,inc(increment), op(oper) {}
T operator () () {T tmp = current;
current = op(current, inc);
return tmp;};
protected:
virtual T default_op(T cur, T incr) {return cur+incr;};
private:
T current;
T inc;
T (*op)(T st, T inc);
};
template <class T>
T molt(T current, T increment)
{
return current * increment;
}
vector <double> viota(10);
...
generate(viota.begin(),viota.end(), iota_gen<double>(0.1,1.5,molt));
...
|
|
|
|
|
|
|
#3 |
|
Senior Member
Iscritto dal: Jan 2000
Messaggi: 551
|
Grazie Cionci
avevo avuto l'idea dei puntatori ma non sapevo esattamente come farla. la tua è una ottima idea. La esamino meglio adesso. |
|
|
|
|
|
#4 | |
|
Bannato
Iscritto dal: Nov 2002
Città: PV
Messaggi: 1210
|
Re: STL: Farsi un fuctor iota sofisticato(Cionci ,Marco invi
Quote:
Mi spieghi come funz?? E un puntatore a funzione vero? |
|
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3736
|
ma che cavolo di programma stai scrivendo???
|
|
|
|
|
|
#6 | |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Re: STL: Farsi un fuctor iota sofisticato(Cionci ,Marco invi
Quote:
T (*op)(T st, T inc); T è il valore di ritorno...op è il nome del puntatore (c'è * davanti perchè è un puntatore)...il resto sono i parametri... Non importa specificare i nome dei parametri formali (anzi non ha molto senso specificarli)... Meglio sarebbe scrivere così (anche io era da molto che non li usavo): T (*op)(T, T); In pratica op può accettare solo funzioni il cui tipo di ritorno è T e i parametri sono 2 di entrambi di tipo T... |
|
|
|
|
|
|
#7 |
|
Senior Member
Iscritto dal: Jan 2000
Messaggi: 551
|
Dunque cionci,ieri ho fatto delle prove e
il compilatore mi segnala problemi solo quando lo chiamo senza specificare la funzione: generate(viota.begin(),viota.end(), iota_gen<double>(1.0 , 2.0)); (non so;dovrebbe per come ho capito,richiamare default_op ma mi segnala questo: Error E2034 riempvec.cpp 63: Cannot convert 'double (iota_gen<double>::*)(double,double)' to 'double (*)(double,double)' in function main() Error E2151 riempvec.cpp 63: Type mismatch in default value for parameter 'oper' in function main() ) Comunque le tue indicazioni sono state preziosissime e ti spiego perchè. 1)Ho capito che l'operazione da usare doveva essere memorizzata nella classe. 2)Volevo usare i functor standard e dopo una mezz'ora di tentativi assurdi in cui dichiaravo l'operazione come binary_function (non ti dico che usciva!) 3)Mi sono fermato a pensare,e ho concluso che plus divides etc in fondo non erano che degli oggetti(la cosa non mi era proprio chiarissima) quindi bisognava dichiararli e usarli (un'altra mezz'ora per concludere che dovevo metterli nel template Codice:
template <typename T ,typename TFOO>
class iota_gen3 {
public:
iota_gen3(T start,T increment,TFOO tfo )
: current(start) ,inc(increment) ,foo(tfo) {}
T operator () () {T tmp = current;
current = foo(current, inc);
return tmp;};
private:
T current;
T inc;
TFOO foo;
};
(perchè quando si tratta di template me ne vado subito e sempre nel pallone) Codice:
//Esempi di chiamata generate(viota.begin(),viota.end(), iota_gen3<double ,multiplies<double> >(1.0,2.0,multiplies<double>())); generate(viota.begin(),viota.end(), iota_gen3<double ,minus<double> >(10.0,1.0,minus<double>())); Vedi un pò tu se si può aggiustare qualcosa (la chiamata non è un esempio di leggibilità Comunque grazie per avermi fatto vedere come si usa un puntatore a funzione in una classe. Credo che l' 80 % del merito di iota_gen3 sia tuo. (Quanno ce vò ce vò A proposito: Chiamare una funzione tramite puntatore(a funzione) è + veloce rispetto ad una normale? Ps.scusate il papiello |
|
|
|
|
|
#8 | |
|
Senior Member
Iscritto dal: Jan 2000
Messaggi: 551
|
Quote:
Sto scrivendo la mia tesi,questo codice mi è servito realmente(leggi sopra a cosa). La morale di verloc sulla STL: quando vedi per la prima certe funzioni,tu dici : "Daiiiii ... a chi puo fregare di queste str*****e ?" Poi arrivi ad incocciarle "Luke...non sottovalutare il lato oscuro della STL" |
|
|
|
|
|
|
#9 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Bene
Riguardo alla velocità... Direi proprio di no... Visto che bisogna andare ad accedere in memoria per recuperare l'indirizzo della funzione che altrimenti sarebbe calcolato automaticamente in fase di compilazione... |
|
|
|
|
|
#10 |
|
Bannato
Iscritto dal: Jul 2000
Città: Malo (VI)
Messaggi: 1000
|
Vedo che avete gia' fatto tutto voi
Solo un paio di piccoli suggerimenti per la leggibilita'. La prima e' quella di aggiungere un parametro di default per l'oggetto da utilizzare, Codice:
template <typename T ,typename TFOO>
class iota_gen3 {
public:
iota_gen3(T start,T increment,TFOO tfo [b]=TFOO()[/b] )
: current(start) ,inc(increment) ,foo(tfo) {}
Codice:
//Esempi di chiamata generate(viota.begin(),viota.end(), iota_gen3<double ,multiplies<double> >(1.0,2.0)); generate(viota.begin(),viota.end(), iota_gen3<double ,minus<double> >(10.0,1.0)); Codice:
template <typename T , typename TFOO>
iota_gen3<T,TFOO> mk_iota( T x , T y , TFOO z )
{
return iota_gen3<T,TFOO>(x,y,z);
}
Codice:
generate(viota.begin(),viota.end(), mk_iota(1.0,2.0, multiplies<double>() )); Codice:
multiplies<double> mul; generate(viota.begin(),viota.end(), mk_iota(1.0,2.0,mul )); |
|
|
|
|
|
#11 |
|
Senior Member
Iscritto dal: Jan 2000
Messaggi: 551
|
Semplicemente Meraviglioso,Marco!
Non scherzo se dico che tu e Cionci date delle botte di progresso enormi alle mie conoscenze di apprendista. Sul serio,credetimi! E' riconoscenza,non piaggeria! Mercì |
|
|
|
|
|
#12 |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
E' /\/\@®¢Ø il mago della STL
|
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 08:21.



















