Newsgroup: it.comp.lang.c++
Titolo: Problema con i template e overloading di operatori

Ciao,
ho 2 classi, strutturate in questo modo: Autore è subclass di Persona.
Persona:
class Persona
{
public:
	Persona();
	Persona(string nome, string cognome);
	virtual ~Persona();
	void setNome(string nome);
	void setCognome(string cognome);
	string getNome() const;
	string getCognome() const;
	template <class T> bool operator== (T ) const;
	friend istream& operator>>(istream&, Persona&);
	virtual ostream& stampa(ostream& os) const;
protected:
	string nome;
	string cognome;
};
inline ostream& operator<<( ostream& os, const Persona& pers)
{
  return pers.stampa(os);
}
#include "Persona.h"
Persona::Persona() {
}
Persona::Persona(string n, string c)
{
	nome = n;
	cognome = c;
}
Persona::~Persona()
{
}
void Persona::setNome(string n) {
	nome = n;
}
void Persona::setCognome(string c) {
	cognome = c;
}
string Persona::getNome() const{
	return nome;
}
string Persona::getCognome() const{
	return cognome;
}
ostream& Persona::stampa(ostream& os)const{
  os << "Nome: \t" << nome << endl;
  os << "Cognome: \t" << cognome << endl;
  return os;
}
istream& operator>>(istream& is, Persona& p) {
	char nome[250];
	char cognome[250];
	cout << "Inserisci il nome: ";
	is.getline(nome,250);
	cout << "Inserisci il cognome: ";
	is.getline(cognome,250);
	p = Persona(nome,cognome);
	return is;
}
template <class T> bool Persona::operator== (T p) const {
	if (!stricmp(this->nome,p->getNome()) == 0 &&
!stricmp(this->cognome,p->getCognome()))
		return true;
	else
		return false;
}
Autore:
#ifndef AUTORE_H_
#define AUTORE_H_
using namespace std;
#include "Persona.h"
class Autore : public virtual Persona
{
public:
	Autore();
	Autore(string nome, string cognome,string linguaScrittura);
	virtual ~Autore();
	void setLinguaScrittura(string ls);
	string getLinguaScrittura() const;
	friend istream& operator>>(istream&, Autore&);
	virtual std::ostream& stampa(std::ostream& os) const;
private:
	string linguaScrittura;
};
#endif /*AUTORE_H_*/
using namespace std;
#include "Autore.h"
Autore::Autore()
{
}
Autore::Autore(string n, string c, string ls) : Persona(n,c)
{
	nome = n;
	cognome = c;
	linguaScrittura = ls;
}
Autore::~Autore()
{
}
void Autore::setLinguaScrittura(string ls) {
	linguaScrittura = ls;
}
string Autore::getLinguaScrittura() const {
	return linguaScrittura;
}
std::ostream& Autore::stampa(std::ostream& os)const{
	os << "Nome: \t" << nome << endl;
	os << "Cognome: \t" << cognome << endl;
	os << "Lingua di scrittura: \t" << linguaScrittura << endl;
	return os;
}
istream& operator>>(istream& is, Autore& a) {
	char nome[250];
	char cognome[250];
	char linguaScrittura[250];
	cout << "Inserisci il nome: ";
	is.getline(nome,250);
	cout << "Inserisci il cognome: ";
	is.getline(cognome,250);
	cout << "Inserisci la lingua di scrittura: ";
	is.getline(linguaScrittura,250);
	a = Autore(nome,cognome,linguaScrittura);
	return is;
}
--------------------------------------------------------------------------------------------
Il problema è che se scrivo il seguente codice:
         Persona a1;
         cin >> a1;
       Persona a2;
         cin >> a2;
	if (a1 == a2) {
	}
Il compilatore non dà errori in compilazione, ma il linker sì:
Invoking: GCC C++ Linker
g++  -o"myprj.exe"  ./src/Autore.o ./src/myprj.o ./src/Persona.o
./src/myprj.o:myprj.cpp:(.text+0x320): undefined reference to `bool
Persona::operator==<Persona>(Persona) const'
collect2: ld returned 1 exit status
make: *** [myprj.exe] Error 1
make: Target `all' not remade because of errors.
Cosa sto sbagliando?
Grazie

 make: Target `all' not remade because of errors.
Prima di tutto la definizione della funzione template deve andare nel
file header, altrimenti il compilatore non sa come instanziarla (modulo
'extern', che comunque non ? molto supportato).
Se anche facessi questa modifica il compilatore andrebbe ad istaziare il
template con la signature che segnala il linker, e cercherebbe di usare
l'operatore -> su un oggetto di tipo Persona. Ergo passa un reference
(spannometricamente: se devi passare una classe ad una funzione/metodo
passa per reference, al limite costante - non passare per copia).
Poi: l'operatore di confronto non dovrebbe modificare gli operandi
quindi anche quello di sinistra pu? essere const.
Quello che ti serve ?:
template <class T>
bool Persona::operator==(T const &p) cont {
        if (...)
                return true;
        else
                return false;
}
Luca
-- 
E' bene ricordare che l'intero Universo ? formato,
con un'unica trascurabile eccezione, dagli "altri".
John Andrew Holmes


Ciao,
ti ringrazio per l'aiuto ma sembra avere ancora problemi. Ho modificato
così:
// Persona.h
class Persona
{
public:
	[...]
	template <class T> bool operator== (const T&) const;
protected:
	[...]
};
// Persona.cpp
#include "Persona.h"
template <class T> bool Persona::operator==(const T &p) const {
	if (stricmp(this->nome,p->getNome()) == 0 &&
stricmp(this->cognome,p->getCognome())==0)
		return true;
	else
		return false;
}
L'errore che ottengo è lo stesso:
Building target: myproj.exe
Invoking: GCC C++ Linker
g++  -o"myproj.exe"  ./src/Persona.o
./src/myproj.o:myproj.cpp:(.text+0x464): undefined reference to `bool
Persona::operator==<Persona>(Persona const&) const'
collect2: ld returned 1 exit status
make: *** [myproj.exe] Error 1
make: Target `all' not remade because of errors.
Build complete for project myproj
Come posso fare?
Grazie!

 Come posso fare?
RTFA per favore.
Luca
-- 
Alcuni pensano che io sia una persona orribile, ma non e` vero. Ho il
cuore di un ragazzino - in un vaso sulla scrivania.

> 'extern', che comunque non è molto supportato).
Hai ragione, non me ne sono proprio accorto.
Ho provato, nel file Persona.h, a definire il template così:
template <class T> extern bool operator== (T ) const;
[come viene indicato su:
http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.xlcpp8a.doc/language/ref/explicit_instantiation.htm
]
Però ottengo sempre errori:
../Persona.h:25: error: storage class specified for member operator
`operator=='
Ho provato con:
extern template <class T> bool operator== (T ) const;
Ma lo stesso errori:
../Persona.h:25: error: expected unqualified-id before "template"

Michele 'xjp' ha scritto:
Ok, ho risolto in questo modo. Il template si deve mettere nell'header
file, non nel cpp (come facevo io):
#ifndef PERSONA_H_
#define PERSONA_H_
#include <iostream>
#include <string>
using namespace std;
class Persona
{
public:
	Persona();
	Persona(string nome, string cognome);
	virtual ~Persona();
	void setNome(string nome);
	void setCognome(string cognome);
	string getNome() const;
	string getCognome() const;
	template <class T> bool operator== (T const & ) const;
	friend istream& operator>>(istream&, Persona&);
	virtual ostream& stampa(ostream& os) const;
protected:
	string nome;
	string cognome;
};
inline ostream& operator<<( ostream& os, const Persona& pers)
{
  return pers.stampa(os);
}
template <class T> bool Persona::operator==(T const &p) const {
	if (this->nome == p.getNome() && this->cognome == p.getCognome())
		return true;
	else
		return false;
}
#endif /*PERSONA_H_*/