Newsgroup: it.comp.lang.c++
Titolo: friend e template

Ciao a tutti.
Ho dei problemi con l'utilizzo delle funzioni friend nelle classi template.
Il seguente codice compila correttamente ma in fase di linking viene
generato un errore Unresolved external 'operator *' per ogni funzione friend
(utilizzo il bcc32 free a riga di comando e lo stesso problema l'ho
riscontrato con il g++).
Qualcuno puņ aiutarmi a capire dove sbaglio? Grazie a tutti per le risposte.
template <class T>
class B;
template <class T>
class A
{
   private: T x; /* ecc... */
   protected: /* ecc... */
   public:
      A(){x=0;} /* ecc... */
      /* A<T> * A<T> --> T */
      T operator*(A<T> a);
      /* B<T> * A<T> --> A<T> */
      friend A<T> operator*(B<T> b, A<T> a);
      /* A<T> * B<T> --> A<T> */
      friend A<T> operator*(A<T> a, B<T> b);
};
template <class T>
class B:public A<T>
{
   private: T y; /* ecc... */
   protected: /* ecc... */
   public:
      B(){y=0;} /* ecc... */
      /* B<T> * B<T> --> B<T> */
      B<T> operator*(B<T> b);
      /* B<T> * A<T> --> A<T> */
      friend A<T> operator*(B<T> b, A<T> a);
      /* A<T> * B<T> --> A<T> */
      friend A<T> operator*(A<T> a, B<T> b);
};
template <class T>
T A<T>::operator*(A<T> a) {return x*a.x;}
template
<class T> B<T> B<T>::operator*(B<T> b) {y*=b.y;return *this;}
template
<class T> A<T> operator*(B<T> b, A<T> a) {A temp;temp.x=b.y*a.x;return
temp;}
template
<class T> A<T> operator*(A<T> a, B<T> b) {A temp;temp.x=a.x*b.y;return
temp;}
int main()
{
 A<int> Y; B<int> Z;
 Y*Y; // ok
 Z*Z; // ok
 Y*Z; // Unresolved external 'operator *(A<int>, B<int>)'
 Z*Y; // Unresolved external 'operator *(B<int>, A<int>)'
 return 0;
}

 stesso problema l'ho riscontrato con il g++).
E' una questione di cui si è già parlato un po' di volte.
In sostanza, la seguente espressione
  friend A<T> operator*(B<T> b, A<T> a);
non dichiara friend la funzione template che stai per definire, bensì
dichiara friend (e implicitamente introduce) una diversa funzione *non*
template. (Se noti, il messaggio d'errore fa riferimento a una funzione
ordinaria, non a un'istanziazione di una funzione template.)
Soluzione: anticipa la dichiarazione delle funzioni template e riscrivi la
dichiarazione friend così:
 friend A<T> operator*<T>( B<T> b, A<T> a );
o anche così:
 friend A<T> operator*<>( B<T> b, A<T> a );
Max

 E' una questione di cui si è già parlato un po' di volte.
Scusate se mi intrometto ma interessa anche me. Ho modificato così il
codice
template <class T>
class B;
template <class T>
class A;
template <class T> A<T> operator*(B<T> b, A<T> a);
template <class T> A<T> operator*(A<T> a, B<T> b);
template <class T>
class A
{
   private: T x; /* ecc... */
   protected: /* ecc... */
   public:
      A(){x=0;} /* ecc... */
      /* A<T> * A<T> --> T */
      T operator*(A<T> a);
      /* B<T> * A<T> --> A<T> */
      friend A<T> operator*<>(B<T> b, A<T> a);
      /* A<T> * B<T> --> A<T> */
      friend A<T> operator*<>(A<T> a, B<T> b);
};
template <class T>
class B:public A<T>
{
   private: T y; /* ecc... */
   protected: /* ecc... */
   public:
      B(){y=0;} /* ecc... */
      /* B<T> * B<T> --> B<T> */
      B<T> operator*(B<T> b);
      /* B<T> * A<T> --> A<T> */
      friend A<T> operator*<>(B<T> b, A<T> a);
      /* A<T> * B<T> --> A<T> */
      friend A<T> operator*<>(A<T> a, B<T> b);
};
template <class T> T A<T>::operator*(A<T> a) {return x*a.x;}
template <class T> B<T> B<T>::operator*(B<T> b) {y*=b.y;return *this;}
template <class T> A<T> operator*(B<T> b, A<T> a) {A<T>
temp;temp.x=b.y*a.x;return temp;}
template <class T> A<T> operator*(A<T> a, B<T> b) {A<T>
temp;temp.x=a.x*b.y;return temp;}
int main()
{
 A<int> Y; B<int> Z;
 Y*Y; // ok
 Z*Z; // ok
 Y*Z; // Unresolved external 'operator *(A<int>, B<int>)'
 Z*Y; // Unresolved external 'operator *(B<int>, A<int>)'
 return 0;
}
ma, mentre il BCC55 me lo compila senza errori, il GCC (in realtà il
DJGPP, una versione non molto recente) mi dà il seguente errore:
FRIEND E TEMPLATE.cc: In instantiation of `A<int>':
FRIEND E TEMPLATE.cc:47:   instantiated from here
FRIEND E TEMPLATE.cc:22: invalid use of undefined type `class A<int>'
FRIEND E TEMPLATE.cc:23: forward declaration of `class A<int>'
FRIEND E TEMPLATE.cc:22: confused by earlier errors, bailing out
Mi sfugge qualcosa o ha ragione BCC55?
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

 Mi sfugge qualcosa o ha ragione BCC55?
Ho compilato il codice con successo con Dev-C++ 4.9.8.0 (GCC 3.2) e credo
che il problema sia la versione non recente del compilatore.
Ciao.

 che il problema sia la versione non recente del compilatore.
Grazie della conferma.
