Newsgroup: it.comp.lang.c++
Titolo: errori = friends + templates;

Salve a tutti,
Non saltate subito sulla sedia, perchè ovviamente l'assegnazione in oggetto
vale solo per me.
Comunque non sapevo che altro scrivere per sintetizzare il problema.
Mi spiego. Ho un programma che mi da due diversi errori durante la
compilazione. Di seguito riporto la parte interessata del codice ( i tre
punti "..." significano che non riporto una o più linee per esigenza di
essere breve ).
// file database.h
...
template <typename T>
class DataBase
{
   public:
      DataBase();
   private:
      fstream dataFile;
      string fName;
      void run();
      void add( T & );
      bool find( const T & );
      void modify( const T & );
      void remove( T & );
      ostream& print( ostream & );
      friend ostream& operator<<(ostream &out, DataBase<T> &db)
                  { return db.print( out ); }
};
...
// file database.cpp
...
template <typename T>
DataBase<T>::DataBase()
	{...}
template<typename T>
void DataBase<T>::run()
	{...}
... // qui per voi non copio tutte le definizioni
// file usedb.cpp
...
#include "DataBase.h"
#include "Person.h"
...
int main()
{
   DataBase<Person> db; // usedb.cpp:11 (errore)
   ...
   return 0;
}
1) Non è la prima volta che uso i template, ma sto facendo qualche stupido
errore, perchè ottengo dal compilatore ( o meglio, dall'editor linker ):
/database/src/usedb.cpp:11: undefined reference to
`DataBase<Person>::DataBase[in-charge]()'
La riga 11 è commentata nel sopra riportato codice.
Stesso errore anche se istanzio
   DataBase<int> db;
2) Secondo ed ultimo. Avrete notato una friend della classe con overloading
dell'operatore "<<". Così come l'ho riportato non da problemi.
Però se estraggo l'implementazione della funzione dal file DataBase.h per
scriverla nel DataBase.cpp ottengo degli avvertimenti (warnings) che non
capisco.
Faccio così:
// file DataBase.h
...
friend ostream& operator<<( ostream &out, DataBase<T> &db );
...
// file DataBase.cpp
...
template<typename T>
ostream& operator<<( ostream &out, DataBase<T> &db )
	{ return db.print( out ); }
...
Ed ecco gli errori:
/src/database.h:31: warning: friend declaration `std::ostream&
operator<<(std::ostream&, DataBase<T>&)' declares a non-template function
/src/database.h:31: warning: (if this is not what you intended, make sure
the function template has already been declared and add <> after the
function name here) -Wno-non-template-friend disables this warning
Ok, questo è tutto.
Ringrazio chiunque voglia aiutarmi a capire dove sto sbagliando.
Ciao,
FabioMDF
 
--------------------------------
Inviato via 
http://arianna.libero.it/usenet/

 function name here) -Wno-non-template-friend disables this warning
Fai quello che il messaggio di warning suggerisce di fare (dove dice "make 
sure etc...").
Anche qui vale quanto detto a proposito del costruttore: l'implementazione 
della funzione template deve essere visibile nel punto in cui viene 
instanziata.
Max

 capisco.
Questo non č un errore ma dipende dal fatto che stai dichiarando una
funzione non template all'interno di un template, il compilatore ti
consiglia giustamente cosa fare (puoi mettere la funzione anche esternamente
al template):
template <typename T> ostream& operator<<( ostream &out,Database<T> &db)

 Max
Come avevo scritto, inizialmente la funzione operator<<() era per intero
implementata nel file database.h e non c'erano i warnings che sono venuti
fuori quando ne ho spostato l'implementazione su database.cpp.
Avevo sempre creduto di potere dichiarare le funzioni nei file .h per poi
descriverne l'implementazione in un .cpp includendo il precedente, ma
evidentemente ci sono delle notevoli eccezioni.
Comunque mi sai consigliare un qualche documento a proposito di queste
regole di visibilità o più in generale su come distribuire le unità di
compilazione di un progetto?
Grazie,


 compilazione di un progetto?
Grazie a chi ha risposto, e anche a chi ha solo letto ...
Per chi fosse interessato a questo argomento, ho trovato le risopste
definitive (1?) su:
 
http://www.parashift.com/c++-faq-lite/
[34.12] Why can't I separate the definition of my templates class from
it's declaration and put it inside a .cpp file?
[34.13] How can I avoid linker errors with my template functions?
Ciao,


 ...
Devi prima dichiarare la funzione template:
  template <typename T> 
   ostream& operator<<( ostream &out,Database<T> &db )
e quindi aggiungere "<>" nella dichiarazione friend:
  friend ostream& operator<< <> (ostream &out, DataBase<T> &db);
Max