Newsgroup: it.comp.lang.c++
Titolo: overload di operator[]

Ho la classica classe vector, beh non
proprio "classica" dato che deve gestire
dei dati da file in modo paginat, comunque
il concetto č che avrei bisogno di distinguere
due situazioni:
template <class T>
class Vectorizer {
...
}
Vectorizer<char> V( ... nomefile ... );
t=V[intice];
V[indice]=t;
nel primo caso l'operatore deve solo cercare in quale
pagina del file sta il dato (in funzione del tipo di dato,
č per questo che il tipo Vector č anche un template...), caricare
il frame in memoria (ho un'altra classe che fa da "paginatore")
e restituire l'indirizzo del dato da leggere; fin qui nessun
problema, la stessa cosa andrebbe bene anche per "scrivere" un
dato nella pagina restituita dal "paginatore" dato che operator[]
restituisce un T& ma in quel caso va settato il flag di "scrittura"
della relativa pagina, cosa che non va ovviamente fatta se č una
semplice lettura.
Mi č stato detto che si puň distinguere le due cose cosě:
T& operator[](long index); // se uso [] a sinistra di un =
T& operator[](long index) const;  // se uso [] a destra di un =
ma ovviamente non mi funziona.
Il mio compilatore č:
g++ (GCC) 3.2.2 [FreeBSD] 20030205 (release)
Grazie per i consigli.
SiMoStro

 CUT
Ho risolto con una classe Proxy.
Tuttavia molto inefficiente.
SiMoStro


Il problema stà nel fatto che la chiamata a "T& operator[](long index)
const" deve stare dentro una funzione o membro dove la variabile è
dichiarata come const. Infatti l'overload dell'operatore non-const è
Read-Write, mentre quello const è solo Read. Allora come farebbe il
compilatore a capire quale operatore richiamare senza ulteriori
informazioni?
Quindi per esempio:
Vectorizer<char> V;
char t ='A';
...
V[indice] = t;  //chiama l'operatore non-const read/write
...
void Read (const Vectorizer<char>& V, int& indice) {
 char t = V[indice];    //chiama l'operatore const read
}

 informazioni?
Indubbiamente, ragionandoci un istante, si intuisce
che non è facile dirimere l'ambiguità.
C'è anche da dire che, stando a casi di tipi che non
siano puntatori, le semantiche di:
t=vec[index];
vec[index]=t;
per l'operatore di assegnamento sono "abbastanza" separabili: se la
variabile "t" è un tipo fondamentale, ad esempio "char", la chiamata
a char.operator=() non ha senso, cioè per il primo assegnamento si
utilizza il naturale:
t=vec.operator(index);
che in questo senso ha il significato di "selezione di index per
assegnamento a t"; il secondo assegnamento ancora una volta può
essere interpretata solo come:
vec.operator[index]=t;
cioè "selezione di index per assegnamento a vec".
In effetti, se l'operatore [] viene sovraccaricato come:
T& Vectorizer<T>::operator[](const long index){
 ...
return &( ...operazione...);
}
funziona in entrambi i casi, ma i due casi coincidono mentre
per il primo (il t=vec[index]) è chiaro che si potrebbe
enfatizzare l'idea di "sola lettura" (operatore usato a destra di un
assegnamento) con il const; purtroppo una funzione const ha il significato
che si conosce e "renderlo particolare" solo per operator[] sarebbe forse
chiedere troppo.
Ho risolto così:
template <class T>
class Vectorizer {
// ********************************
  class Proxy {
    friend class Vectorizer<T>;
    public:
    T& operator=(T value) {
      p_Vec->paginatore->set_dirty();
      return *(p_Vec->actual_value);
    }
    operator T(){
      return *(p_Vec->actual_value);
    }
    private:
    Vectorizer<T>* p_Vec;
    Proxy(Vectorizer<T>* p_Vec_): p_Vec(p_Vec_) {}
  };
// ********************************
  int dim_T;
  T* actual_value;
 // per evitare costruzioni di Proxy ad ognoi chiamata di operator[]
  Proxy my_proxy;
  Pager* paginatore;
  string nomefile;
public:
Vectorizer( ... );
~Vectorizer();
 ...
Proxy operator[](const long index)
{
  page_id page;
  address_id offset, addr;
  addr=index*dim_T;
  offset=OFFSET(addr);
  page=PAGE(addr);
  actual_value=((T*)(paginatore->resolve_address(page))+offset);
  return my_proxy;
}
...
}
SiMoStro

 T& operator[](long index) const;  // se uso [] a destra di un =
Il secondo mi pare sbagliato, direi piuttosto:
const T & operator[](long index) const;
 
Dan