Newsgroup: it.comp.lang.c++
Titolo: Operator[](int) non è un lvalue?

Ciao,
sto definendo una piccola classe array speciale
e ho bisogno di un operatore di indicizzazione
per accedere agli elementi, cosě ho scritto:
int operator[](int){return Reg[i]; };
Ora perň mi succede questo: se scrivo
x = MyArr[i];
va tutto bene, ma se scrivo
MyArr[i] = X;
il compilatore mi spara un errore "Lvalue required"...
Perchč? Per caso devo definire anche
un operator= per l'assegnamento?

 un operator= per l'assegnamento?
no, no è questo il problema
ecco il prototipo che ti consente l'assegnamento:
int& operator[](int i){ return Reg[i];}
ora questa istruzione è valida:
MyArr[i] = X;
attento però che questo operatore(e quello che hai fornito tu) non funziona
su oggetti costanti e devi definirne anche uno così:
int operator[](int i)const{ return v[i];} // accesso in sola lettura degli
elementi
Permettimi una curiosità. Come mai hai bisogno di crearti una classe array?
La STL non ti può venire in aiuto?
Ciao
TheNix

 La STL non ti può venire in aiuto?
Dunque... con la STL sono a zero, non l'ho mai usata
e mi ispira sospetto & diffidenza (Template? Che roba
sono, delle specie di macro? MAH!) :-)
A parte questo,
1) ne uso molti, li creo dinamicamente e possono
	essere di lunghezze diverse e non note
	a priori;
2) ci sono delle trasformazioni da fare su questi
	array che non hanno bisogno di (molti) dati
	esterni e che quindi possono benissimo
	scriversi come metodi, ma soprattutto
3) mi piaceva scriverli così :-P
Con la modifica che hai suggerito il prog compila,
ma appena entra nel distruttore del primo oggetto
array mi spara un errore di runtime "Access violation
at address XXXXXX in module BORLANDMM.DLL... azz :-(
Ti posto il codice di costruttori e distruttori:
// N=dimensione della scacchiera
Soluzione::Soluzione(int N)
{
Regine = (int *)malloc(sizeof(int)*(N+1));
R= (int *)malloc(sizeof(int)*(N+1));
Dim = N;
Valida=false;
};
// A=array con una soluzione già pronta:
// A[0]=dimensione della scacchiera
Soluzione::Soluzione(int *A)
{
Regine = (int *)malloc(sizeof(int)*(A[0]+1));
R= (int *)malloc(sizeof(int)*(A[0]+1));
Dim = A[0];
for (int i=0; i<A[0]; Regine[i]=A[i++]);
Valida=true;
};
// Dealloca i due array
Soluzione::~Soluzione()
{
free(Regine);
free(R);
};

 at address XXXXXX in module BORLANDMM.DLL... azz :-(
OK OK colpa mia... trovato l'errore :-)

 3) mi piaceva scriverli così :-P
cmq per capire i template ti consiglio di studiarli  su un buon libro C++.
(Speriamo di non averti confuso le idee riguardo i template :-)  ). La STL è
un po difficile all'inizio però è molto utile.Ti consiglio di studiarla.
Ciao

 sono, delle specie di macro? MAH!) :-)
Intanto, per favore, chiamatela con il suo vero nome di Standard C++
Library. La STL è un'altra cosa. E poi... diffidenza? Se non ti piace il
C++ perché lo usi? Quando usi il C, la sua libreria standard ti ispira
forse diffidenza?
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


Non mi sembra di aver danneggiato nessuno chiamando STL la libreria standard
che implementa (tra le altre cose) i contenitori in C++. Se non sbaglio tra
i suoi header spunta spesso l'acronimo STL (standard template library).
Molti libri sul C++ (se non tutti) si riferiscono ad essa usando lo stesso
acronimo.
Non riesco proprio a capire il tuo sfogo...

 Non riesco proprio a capire il tuo sfogo...
Non era uno sfogo ma solo una precisazione. Se parli di STL stai
parlando di una libreria esterna che non fa parte del C++ standard.
Quella standard si chiama, appunto, libreria standard del C++. I libri
seri e aggiornati la chiamano cosě.


Non riesco proprio a capire il tuo sfogo...
Sui NGs si tende ad attribuire il tono che si vuole alle email che si
leggono. Se rileggi la mail di EMG con un tono calmo e rilassato e' un
conto, le la leggi con tono arrabbiato e scocciato e' un'altro conto!!!!
Forse la vera interpretazione sta nel mezzo, e credo non ci sia nulla di
male. Gli errori vanno corretti (STL -> SL), i pregiudizi pure!
Tommy

 int operator[](int i)const{ return v[i];}
Dunque... NO :-)
Stamani ho testato il programma con + calma e...
ho trovato che il primo operator (int& ecc. ecc.)
in realtà restituisce una struct con 4 membri
dati. O perlomeno questo è ciò che mostra il
debugger. Insomma eseguendo le istruzioni
MyArr[1]=3;
int x=MyArr[1];
si ottiene x=<un numero casuale> che non è proprio
quello che volevo ottenere :-D

 forse diffidenza?
Uso il C++ perchè mi fanno comodo alcune novità
che introduce: le classi, la possibilità di
strutturare meglio il codice. Mi secca molto
invece il fatto che sia più fiscale del C sul
controllo dei tipi. Insomma uso il C++ come un
C migliorato.
Ma sinceramente molte volte (come qui con gli
operatori) trovo che il C++ si perda in inutili
sottigliezze semantiche: se uno scrive un operator[]
(di qualunque genere) è perchè vuole che la classe
possa essere usata (anche) come un array: e allora
perchè distinguere la lettura dalla scrittura? Se uno
vuole trattare diversamente i 2 casi ci pensa
nell'implementazione dell'operatore, semmai.
Queste sono complicazioni inutili.
Per questo non uso STL o template, non ho voglia
di imbarcarmi in altri sofismi grammaticali.
Mi bastano quelli che già mi devo sorbire :-)

 quello che volevo ottenere :-D
Posta il codice, hai sbagliato qualche cosa....
Tommy

 Posta il codice, hai sbagliato qualche cosa....
Ecco qua:
class Soluzione
{
private:
int *Regine;
int *R;
int Dim;
bool Valida;
//	etc. etc.
public:
Soluzione *next;
int& operator[](int i) { return Regine[i];};
int operator[](int i)const{ return Regine[i];};
//	etc. etc.
int Dimensione(void) {return Dim;};
Soluzione(int);
Soluzione(int *);
~Soluzione();
};
Implementazione dei costruttori/distruttori:
Soluzione::Soluzione(int N)
{
Regine = (int *)malloc(sizeof(int)*(N+1));
R= (int *)malloc(sizeof(int)*(N+1));
Dim = N;
Valida=false;
};
Soluzione::Soluzione(int *A)
{
Regine = (int *)malloc(sizeof(int)*(A[0]+1));
R= (int *)malloc(sizeof(int)*(A[0]+1));
Dim = A[0];
for (int i=0; i<=A[0]; Regine[i]=A[i++]);
Valida=true;
};
Soluzione::~Soluzione()
{
free(Regine);
free(R);
};

 quello che volevo ottenere :-D
Guarda il seguente codice. E' scritto male, non e' cosi' che si programma,
ma visto che per scemenze minime funziona (manca di tante cose...e fa schifo
in quelle poche che sono implementate) almeno forse riesci a vedere cosa hai
sbagliato tu (visto che il tuo non funziona):
<CODE>
template <class T>
class MyArray{
public:
    MyArray(int size){
        m_size=size;
        m_ptr=new T[size];
        for(int i=0;i<size;++i){
            m_ptr[i]=0;
        }
    }
    ~MyArray(){
        delete []m_ptr;
    }
    T& operator[](int i){
        if((i<0)||(i>=m_size)){
            // fuori dal range:
            // puoi agire in qualche
            // modo
        }
        return m_ptr[i];
    }
private:
    T *m_ptr;
    int m_size;
};
int main()
{
    MyArray<int> a(10,0);
    for(int i=0;i<10;++i){
        cout << a[i] << " ";
    }
    cout << endl;
    a[2]=33;
    a[5]=45;
    for(int i=0;i<10;++i){
        cout << a[i] << " ";
    }
    cout << endl;
    // SECONDA PARTE:
    MyArray<string> b(5,"EMPTY");
    cout << b[2] << endl;
    b[2]="Tommy";
    cout << b[2] << endl;
    return 0;
}
</CODE>
Spiego un attimo:
MyArray<int> a(10,0);
Questo crea un MyArray di 10 interi e li inizializza tutti a 0.
Con un ciclo for mostro che sono tutti a 0.
a[2]=33;
a[5]=45;
Questo scrive i relativi numeri nelle relative posizioni.
Il secondo for loop mostra il risultato.
Ecco tutto l'output:
0 0 0 0 0 0 0 0 0 0
0 0 33 0 0 45 0 0 0 0
Bene?!?
Ora, giusto per cercar di farti piacere i template....
Abbiamo scritto la nostra classe, ma perche' mai dovrebbe essere limitata
SOLO agli interi?
MyArray<string> b(5,"EMPTY");
In questo modo creo un MyArray di 5 stringhe inizializzate con la stringa
"EMTPY".
cout << b[2] << endl;
b[2]="Tommy";
cout << b[2] << endl;
Bene, guarda il codice e.... l'output:
EMPTY
Tommy
Ok?!?
Ora che cosa hanno di male i template?!? La mia classe e' generica....
Riesce a creare un array di interi, di char, di double, di std::string
etc....
Ora concludo dicendoti, dopo tutto questo discorso:
La mia classe fa schifo, la tua ancora di piu'... se riesci usa vector o uno
degli altri container che fanno parte della Standard Library!
Chiedo scusa al NG per il breve esempio fatto male, ma spero possa aiutare
Stanislao a cambiare idea!
Tommy

int operator[](int i)const{ return Regine[i];}
Inoltre c'e' un mucchio di roba che non usi: R, valida etc...
Posta una versione ristretta con SOLO quello che ti serve (ridotta all'osso)
e
poi un main che provi che dia errore.
A quel punto e' piu' semplice dirti dove hai sbagliato.
In tuta franchezza il tuo codice con:
Soluzione a(10);
cout << a[3] << endl;
a[3]=45;
cout << a[3] << endl;
da me funziona. Prima stampa un numero a caso (quello che si trovava in
quell'area di memoria), poi stampa 45.
nonostante funzioni ci sono tante cose che non vanno pero', non
fraintendermi.
Cerca di essere piu' preciso per favore.
Tommy

 degli altri container che fanno parte della Standard Library!
Mm vabbč... vedremo.
Piuttosto, dicevi che la tua classe manca di un sacco di cose:
per esempio? Che cosa deve avere una classe template per
essere considerata completa?
Ah, e grazie del codice :-)

 essere considerata completa?
Non, non si tratta tanto di "classe template" quanto di classe.
Per le classi template basta qualche accorgimento logico a meno che uno non
si voglia complicare troppo la vita e ... volendo ci si riesce sempre.
Dicevo che la classe fornita da me non e' sicura, non controlla gli indici,
non verifica se l'allocazione dell'oggetto e' avvenuta. Non permette usare
oggetti "const"  di quella classe. Tante altre cose. Etc....
Manca quindi quasi di tutto.
Il mio discorso si riferiva al fatto che la mia classe non voleva altro che
essre un array che funziona peggio del normale array C.
std::vector e' gia' fatta, contiene tantissima "roba" utile, non ha bugs, e'
gia' testata, e' performante, usata da tutti etc...
Ti serve invece una lista? std::list, idem.
Insomma non serve re-inventare la ruota, esiste gia'! Usiamola.
Se invece uno programma per scopi didattici il discorso cambia... la ruota
va re-inventata per scoprire come funziona!
Tommy

 Tommy
:-)
non c'è problema, hai fatto più che abbastanza
già così... ora me la cavo da solo fino al prossimo
casino :-DDD

 le varie parti.
Personalmente considero l'STL piu' che un insieme di definizioni
specifico (quello di Stepanov, quello di SGI, ecc.) un insieme di
concetti che hanno a che fare con contenitori e algoritmi che e'
possibile applicare ad essi.
In questo senso ritengo perfettamente legittimo usare il termine STL per
riferirsi a quella parte di Libreria Standard che si occupa proprio di
contenitori (e iteratori) e algoritmi.
Lo stesso Stroustrup evita d'impegolarsi in distinzioni pignole quando
scrive:
The C++ Programming Language - 3rd Edition - 3.10
"Every algorithm works with every container without the use of
conversions. This framework, conventionally called the STL [Stepanov,
1994], is extensible..."
Only my 2 (euro) cents.
Ciao
Gian Michele

 1994], is extensible..."
La sezione 3.10 si intitola:
"Standard Library Facilities"
e non STL facilities!
Inoltre mi sa che non hai capito la frase....
Se leggi 16.2.3 STL containers dice:
"The standard library containers and iterators (often called the STL
framework &3.10) can be ........... Tha wasn't the way the STL was designed,
though. The STL was the result of a single-minded search for......."
Bjarne usa chiaramente il termine STL per riferirsi ad una parte della
standard library. Inoltre quando lo fa dice :
convenzionalmente chiamato......
spesso chiamato......
ad indicare la natura errata della parola STL che ri riferisce al lavoro di
Stepanov 1994.
Tommy

 al lavoro di Stepanov 1994.
Guarda, ho accesso sia alla versione originale sia alla traduzione
italiana e non intendo polemizzare quanto esprimere un punto di vista.
Il fatto che Stroustrup accetti senza troppi problemi il termine STL
indica, a mio avviso, accettazione del termine stesso e non certo che
esso sia erroneo. L'avrebbe scritto altrimenti, no? Nel pezzo che hai
citato il riferimento e' all'implementazione particolare derivata
dall'iniziale idea, non al concetto sottinteso che invece e' stato
incorporato nella Libreria Standard.
Secondo me, l'incorporare il concetto "STL" adattandolo, ne legittima
l'uso susseguente.
Ciao
Gian Michele

 wrote
Quanto sei pignolo. Pensi di avere ragione. Io penso di avere ragione.
Inutile andare avanti con questo thread.....
Nessuno ti proibisce di andare avanti a chiamarla STL.
Ricordati pero' che STL non e' la standard library e, propriamente, nemmeno
parte di essa.
Tommy

 propriamente, nemmeno parte di essa.
Mi spiace, serve un po' piu' di questo per convincermi.
Ciao
Gian Michele

>propriamente, nemmeno parte di essa.
Voi due siete esattamente il tipo di persone
che amano il C++ ...
Perchè invece di litigare su inutili dettagli come
i nomi da dare a cose che sono e servono allo stesso
scopo non fate qualcosa di utile e costruttivo?
Come per esempio dirmi dove $&@#% sta il file stl.h
o analogo/analoghi include file per usare queste
library??? :-) :-P

 library??? :-) :-P
http://www.dinkumware.com/manuals/reader.aspx?lib=cpp
Ciao.
-- 
BSD is for UNIX lovers -- linux is for Windows haters.

 scopo non fate qualcosa di utile e costruttivo?
Chiamare le cose con il loro nome non è inutile. E' l'unico modo che
abbiamo di comunicare efficacemente.


 library??? :-) :-P
Non funziona cosi'. La Libreria Standard del C++, cosi' come quella del
C, e' formata da parecchi include files. Se p.e. vuoi usare il tipo
string includerai <string>, se vuoi usare le mappe o le multimappe
includerai <map>.
Alcuni header dipendono da altri, ma non devi preoccupartene perche' le
dipendenze vengono risolte all'interno degli header stessi con una
tecnica utile in molte situazioni:
#ifndef _MioHeader_included
#include "MioHeader.h"
#endif
Ciao
Gian Michele