Newsgroup: it.comp.lang.c++
Titolo: link(er)ror

Ho un progetto piuttosto complesso, composto per la maggior parte di 
template class.
Vi è mai capitato di avere una classe A dichiarata e parzialmente 
definita (funzioni inline) in un file .h e di non poter definire in tale 
file una funzione membro di A che chiami un'altra funzione template 
definita altrove?
Ho una ridefinizione per ogni inclusione del file .h.
Non ricordo mi sia mai capitata una cosa simile.
Non riesco neanche a riprodurre l'errore creando un micro-progetto 
d'esempio.
La situazione è più o meno questa:
======================================
--- t.h ---
#ifndef _INCLUDE_T_
#define _INCLUDE_T_
namespace tile
{
	template <class T>
	class Tile
	{
		template <class T>
		friend bool f(Tile<T>* a);
	};
	template <class T>
	bool f(Tile<T>* a);
}
#include "t.hpp"
#endif
--- t.hpp ---
namespace tile
{
	template <class T>
	bool f(Tile<T>*)
	{
		return true;
	}
}
--- g.h ---
#ifndef _INCLUDE_G_
#define _INCLUDE_G_
#include "t.h"
extern tile::Tile<int> globalT;
#endif
--- g.cpp ---
#include "t.h"
tile::Tile<int> globalT;
--- a.h ---
#ifndef _INCLUDE_A_
#define _INCLUDE_A_
#include "t.h"
#include "g.h"
class A
{
public:
	bool f() { return tile::f(&globalT); }
};
#endif
--- a.cpp ---
#include "a.h"
--- b.h ---
#ifndef _INCLUDE_B_
#define _INCLUDE_B_
#include "t.h"
#include "g.h"
class B
{
public:
	bool f() { return tile::f(&globalT); }
};
#endif
--- b.cpp ---
#include "b.h"
-------------
======================================
Questo codice non dà problemi, infatti, come ho già detto, non sono 
riuscito a ricreare l'errore. Però la situazione è simile, quindi spero 
che qualcuno di voi, grazie all'esperienza, possa ipotizzare una 
possibile causa.
Nel progetto reale, ho "eliminato" l'errore spostando le definizioni di 
A::f() e B::f() nei file a.cpp e b.cpp.
Chiaramente, funziona anche se evito di chiamare tile::f() all'interno 
di A::f() e B::f().
Proprio non capisco di cosa possa trattarsi.
Kiuhnm
P.S. Con informazioni così parziali non pretendo che mi rispondiate. E' 
un tentativo che faccio prima di rassegnarmi a perdere giorni nello 
scandagliare il codice.

Kiuhnm ha scritto:

L'unica cosa che mi viene in mente e' che il compilatore non
possa/voglia mettere il metodo inline e lo trasformi invece in una
chiamata. Quindi la stessa definizione si troverà in tutti i moduli
che includono la classe.
Il non riuscire a riprodurre l'errore potrebbe esserne un sintomo,
visto che in questo caso il metodo è banale.
Ciao

 che includono la classe.
Pare strano, un metodo con signature "inline" (implicita o esplicita) ma 
non-inlinato dovrebbe rimanere un simbolo non esportato (come una funzione 
static), proprio per evitare il ripetersi dello stesso simbolo in piu' 
unita' di compilazione.
--
Marco 

 }
Qui c'e' un errore. Se un template o una sua specializzazione sono
friend non possono essere dichiarati dalla dichiarazione friend.
Dovresti quindi scrivere:
namespace tile
{
	template <class T>
	class Tile;
	template <class T>
	bool f(Tile<T>* a);
	template <class T>
	class Tile
	{
		template <class T>
		friend bool f(Tile<T>* a);
	};
}
Sospetto che non bastera' a risolvere il tuo problema, ma vale la pena
di provare.
Ciao,
Nicola

 visto che in questo caso il metodo è banale.
Come ha detto Marco, un metodo inline non dovrebbe essere esportato.
Comunque, nel mio caso, è la tile::f<>() ad essere ridefinita!
E' come se l'istanziazione venisse ogni volta esportata...
Non vorrei che fosse un problema di VC2005.
Kiuhnm

 di provare.
Devo ricordarmi di non fare questo errore. Il problema è che questa 
situazione mi capita di rado e VC fa passare tutto sotto silenzio.
Appena ho 2 minuti faccio la correzione. Prima devo eliminare circa 1000 
errori che ho aggiunto nel frattempo :-)
Kiuhnm

 di provare.
Hai ragione. Non č cambiato nulla. Comunque per il momento lascio tutto 
com'č. In quel caso la funzione in linea non mi porta nessun vantaggio.
Forse, piů avanti, compilerň il progetto con gcc.
Kiuhnm