Newsgroup: it.comp.lang.c++
Titolo: ancora queue

Salve a tutti,
forse e' un po' OT, ma cosa c'e' di sbagliato in questa definizione?
template <class T> class counting_queue : public std::queue<T>{
 public:
  int in;
  int out;
  void push(const value_type& x) { in++; std::queue<T>::push(x);}
  void pop(){out++; std::queue<T>::pop();}
  counting_queue() : in(0), out(0){}
 };
In VC++ 6.0 mi da' un errore insensato:
"...  Compiler Error C2352
'class::function' : illegal call of non-static member function
The specified nonstatic member function was called in a static member
function.
The following is an example of this error:
class X
{
public:
   static void func1();
   void func2();
   static void func3()
   {
   func1();          // OK, calls static func1
   func2();          // error, calls nonstatic func2
   }
};
..."
quando non c'e' traccia di funzioni statiche in giro!
Usare la STD mi sta creando un sacco di problemi...

 Usare la STD mi sta creando un sacco di problemi...
Forse in parte perche` il tuo approccio e` strettamente O-O, mentre
la libreria standard C++, per la maggior parte, si impernia invece
su di un altro paradigma, quello del 'generic programming'.
Alex

 su di un altro paradigma, quello del 'generic programming'.
E forse anche perche' il supporto da parte del VC++ all' STL non e' dei
migliori...
--
Davide Pirola @ Prograph Research
www.prograph.it
www.protonic.net

 Usare la STD mi sta creando un sacco di problemi...
un update(che forse puo' spiegare l'arcano):
non e' la definizione di counting_queue che provoca l'errore, e neppure
l'istanziazione di una counting_queue, ma piuttosto l'uso di, ad esempio,
pop(). Cioe':
template <class T> class counting_queue : public std::queue<T>{
 public:
  int in;
  int out;
  void push(const value_type& x) { in++; std::queue<T>::push(x);}
  void pop(){out++; std::queue<T>::pop();}
  counting_queue() : in(0), out(0){}
 };
compila correttamente;
main(){
counting_queue<int> a;
}
compila correttamente (a meno di return values..);
main (){
counting_queue<int> a;
a.pop();
}
non compila e da' l'errore descritto sopra.

 
In generale pero' ha ragione Alex Martelli: i contenitori non sono fatti
per essere ereditati (lo si capisce dal fatto che non definiscono metodi
virtuali). La soluzione corretta e' usare un attributo queue nella tua
classe:
template <class T> class counting_queue  {
  private:
    int in;
    int out;
    std::queue<T> theQueue;
  public:
    void push(const value_type& x) { in++; theQueue.push(x);}
    void pop(){out++; theQueue.pop();}
    counting_queue() : in(0), out(0){}
};
 
(Anche questo non l'ho compilato)
Ciao,
Nicola


Penso che sia un bug nell'implementazione del VC6 e si riferisca alla
chiamata std::queue<T>::push.
Purtroppo in questo istante dispongo solo del VC6 base (e non del service
pack 3), quindi non ti so dire se sulle
versioni più recenti è già stato fixato.
Ti consiglio questo work-around (che comunque è anche buona pratica di
programmazione):
template<class T>
class counting_queue : public std::queue<T>
{
 typedef std::queue<T> base;
public:
 int in, out;
 void push(const value_type& x) { in++; base::push(x);}
 void pop(){out++; base::pop();}
 counting_queue() : in(0), out(0){}
};
Definendo un nuovo tipo per la classe base, il VC6 non si "incastra" più con
le chiamate e compila tutto correttamente.
Ciao
-----
Giovanni Bajo
Lead Programmer
Prograph Research S.r.l.
http://www.prograph.it

 
[...]
Non sono sicuro che mi convinca: da una parte, e' vero che tutto cio'
che e' definito in un posto solo e' piu' facile da mantenere, per contro
cambiare classe base mi pare un'operazione cosi' drastica che non trovo
cosi' male che costi fatica...
Ciao,
Nicola