Newsgroup: it.comp.lang.c++
Titolo: Questione di stile

Salve NG,
 
vi pongo un problema al quale ho N soluzioni (e tra le quali ne ho scelta una),
ma vorrei sentire la vostra riguardo a quello che vi sembra più "pulito" o più
"sensato" a livello di codice.
 
Faccio un esempio scemo e non reale, che però racchiude tutti i concetti. Per
questo esempio supponete di non avere a disposizione le STL, ovviamente,
altrimenti è già tutto fatto! :-)
 
Ho bisogno di usare dei containers di vario tipo, ma tutti hanno una funzione
size(), un'operatore [] (potete immaginare cosa ci aspettiamo che facciano) e
una funzione extract(start,len) che ritorna un certo range del contenuto.
Su questi contenitori vogliamo far girare degli algoritmi, che possono prendere
sia un container sia un range; alcuni di questi non modificano gli oggetti,
per cui avranno dei parametri segnati come const.
 
Tutto qua.
Voi come strutturereste una cosa del genere?
 
Ciao!

 
 
Ho fatto un template siffatto:
 
template <class T>
class Data {
public:
    class Part : public Data {
    public:
        Data<T>& data;
        int start, stop;
        virtual int length(void) const {/*..*/}
        virtual T& operator[](int) {/*..*/}
    };
    virtual int length(void) const = 0;
    virtual T& operator[](int) = 0;
    Part extract(int start, int len) {/*..*/}
};
 
gli algoritmi fanno qualcosa tipo (qui ne metto uno che prende due Data e torna
un int):
 
template <class T>
class Alg {
public:
    static int doAlg(Data<T>& d0, Data<T>& d1);
};
 
A questo punto..
La soluzione ovviamente va, ma non mi piace il fatto che, per gestire i const
(mettiamo la doAlg volesse prendere due "const Data<T>&") devo creare un'altra
Part, mettiamo "ConstPart" a causa del membro di tipo Data.
 
Che ne pensate?
 
Ciao!

 Che ne pensate?
 
Non mi piace molto quello che hai fatto, ma forse � perch� non ho capito 
cosa vuoi ottenere esattamente.
 
Non so se pu� essere di aiuto, ma Data e Part mi ricordano vagamente la 
coppia String e Substring, ove quest'ultima possa comportarsi come una 
String.
 
http://www.linux-projects.org/listing/cpp_solutions/11.8/main.cpp
 
 
oppure
 
http://www.linux-projects.org/listing/cpp_solutions/20.6/main.cpp
 
 
 
 
--- news://
freenews.netfront.net/
 - complaints: 
ne...@netfront.net
 ---

 
 
Questa è la stessa cosa che ho scritto io, con la differenza che il mio Part
è una classe innestata e che il Data è template (il che mi farebbe propendere
più per la mia soluzione).
 
Ciao!


Che è corretta
La pratica per iterare su oggetti costanti con const_iterator è ben 
conosciuta
Quindi se vuoi un iteratore e un iteratore che opera su oggetti costanti 
si costruiscono due classi
 

 pi� per la mia soluzione).
 
Ci sono delle sostanziali differenze. String deriva da un contenitore 
standard da cui prende quello che serve e a cui aggiunge la possibilit� 
di estrarre Substring. E con una banale modifica, se vuoi, fai diventare 
template anche String. Secondo non ci sono funzioni virtuali. E in 
ultimo quello � pur sempre un modesto esempio di come sia possibile 
estendere std::string per considerare una sua substring; non pretende di 
essere da modello per tutti i casi *concreti*.


 si costruiscono due classi
 
Ovviamente scrivendo pensavo proprio agli iteratori delle STL, però..
beh, la situazione era un po' diversa e speravo ci fosse una soluzione meno
generale e più snella.
In questo caso in particolare, per me ha molto senso il concetto di range, ma
quello di iteratore sarebbe un'astrazione superflua, quindi esprimere un range
come una coppia di iteratori (sempre ovviamente nel caso che non avessimo
a disposizione le STL) mi suonerebbe come una soluzione "pigra" (nel senso,
scrivo un po' di più perché ho imparato che questa struttura funziona).
 
Come ho scritto già dal topic, non è una domanda "pratica", ma solo di stile o
meglio, se volete, di architettura OO.
Qualche suggerimento in tal senso?
 
Ciao!

 
 
Fermo restando che, se dovessi scrivere del codice che implementa il problema
che ho descritto userei le STL, le String non fanno al caso mio nel caso che
ho descritto: so che mi esprimo male ed era una descrizione un po' troppo
generale, ma spero le precisazioni ulteriori abbiano chiarito un po' meglio
la domanda e il suo scopo.
Detto questo, per quanto riguarda le funzioni virtuali, se c'è un caso d'uso
dove sono quasi fondamentali è questo! Perché tutto questo odio? :-)
 
Ciao!

 scrivo un po' di più perché ho imparato che questa struttura funziona).
 
Se voglio esprimere un range con la possibilità di variarlo la soluzione 
conosciuta, usata e bene accettata da tutti è la coppia  di iteratori
Non c'è niente di male a usare soluzioni che sono ben standardizzate, il 
che va anche bene per la manutenibilità (altri programmatori C++ 
conoscono il concetto di iteratore)
Se poi vuoi cercare altri tipi di soluzioni sei libero di esplorare, ma 
sinceramente, non  ho altre soluzioni.
 
 
 


Perchè l' odio verso le funzioni virtuali ?
Semplice, le funzioni virtuali non possono essere espanse inline anche 
se sono brevi
Infatti andrebbero usate quando servono veramente
Ora, non ho la visione completa della classe, ma da quello che vedo 
chiediti se è necessario per la classe Part ereditare dalla classe Data.
Inoltre perchè  i metodi Part::length e Part::operator [] devono essere 
un override dei corrispondeti metodi di Data ?
Si puo ovviare a ciò ?
E per finire un concetto di design
L' ereditarietà pubblica non è solo un concetto di linguaggio,ma anche 
di un design ben definito
Per l' esattezza l' eredita pubblica è utile  per espandere il concetto 
di oggetto aumentando le sue proprietà rimanendo inalterate 
concettualmente le vecchie
Es: figura_generica  =>  rettangolo in quanto un rettangolo è una figura 
piu specifica e quindi è lecito ereditare
Ora chiediti se un iteratore è anche un container
Ovviamente la risposta è no, quindi dal punto di design non ha senso una 
eredità pubblica
 
 
 
 
 
 
 
 
 
 
 

 eredità pubblica
 
Con gli iteratori a-la-STL infatti il ragionamento che ho fatto sopra perde di
significato perché hanno una struttura totalmente diversa.
 
O meglio, avrebbe significato solo se esistesse un interfaccia "range-able"
che comprendesse sia tutti i contenitori che gli ipotetici oggetti aventi come
membri coppie di iteratori (cosa che ovviamente non esiste e non ha senso nella
filosofia di derivazione delle STL).
Scusate il volo pindarico :)
 
Ciao!

 Scusate il volo pindarico :)
 
Come detto sopra il concetto di container o iteratore generico in STL è 
solo concettuale, non esiste una classe Generic_Container o 
Generic_Iterator proprio per dover usare l' ereditarietà la quale 
penalizza a livello di performance i metodi virtuali e per una libreria 
generica come STL questo era inaccettabile
 
Il concetto di range lo si può istituire con una classe template della 
libreria std chiamata pair (cioè coppia di oggetti)
 
 
 
 
 

 libreria std chiamata pair (cioè coppia di oggetti)
 
Il tuo sviscerare un po' le STL e spiegare il perché sono scritte proprio così
in effetti mi ha ricordato quella differenza tra design e linguaggio che è
fondamentale per avere un codice decente.
 
Non mi rimane molto da fare se non pensarci un po' su con calma per convincermi
che la struttura degli iteratori dei container standard nel caso in oggetto è
quella migliore (il che significa pensare a tutte le alternative che mi vengono
in mente, e magari ritornare qui con altri dubbi!) :-)
 
Ciao!


 
Salute
 


ehehe per carità: serve solo ad coadiuvare il processo maieutico! ;)
Grazie!
 
Ciao!

};
 
una classe annidata che eredita dalla classe contenitore. Ma che senso
ha ? L'allocazione di un oggetto non va in una specie di ricorsione
infinita ?


No, non va in ricorsione infinita
Una classe annidata è come una semplice classe visibilità a parte
 

Una classe annidata è come una semplice classe visibilità a parte
 
Immaginando un costruttore per ogni classe , quello di Part richiama
Data che a sua volta richiama Part che a sua volta richiama Data
etc.... . Non ho provato da codice ma cosi come la leggo mi sembra una
ricorsione infinita.


Dove ?
Non vedo costruttori che chiamano costruttori