n° 185
Maggio/Giugno 2013
Maggio 19, 2013, 11:09:28 am *
Benvenuto! Accedi o registrati.
Hai dimenticato l'e-mail di attivazione?

Accesso con nome utente, password e durata della sessione
Notizia:
 
   Indice   Linux Windows Techassistance Gameassistance videogame hardware Aiuto Ricerca Agenda Downloads Accedi Registrati  

* Messaggi recenti
Messaggi recenti
Pagine: [1]   Vai giù
  Stampa  
Autore Discussione: Metodi template definiti nel file cpp: problemi di linking  (Letto 773 volte)
0 utenti e 1 Utente non registrato stanno visualizzando questa discussione.
Hyde
Global Moderator
Hero Member
*****

Karma: +47/-6
Scollegato Scollegato

Messaggi: 3266


I am a man who walks alone


Mostra profilo WWW
« inserita:: Agosto 30, 2012, 10:40:57 am »

Sto incontrando delle difficoltà nel linkare una classe, creata da me, che implementa 2 metodi pubblici usando i template.
Questi due metodi sono dichiarati nell'header e definiti nel file cpp, insieme con gli altri membri non template della classe.

Ho letto questo articolo su CodeProject su come poter convincere il compilatore/linker avendo scelto di dividere, anche per i due metodi template, la definizione dall'implementazione e utilizzo già con successo questa classe in un progetto dove però essa è richiamata in un unico file, proprio grazie ai suggerimenti di quell'articolo (inclusione del cpp alla fine dell'header togliendolo dal progetto, ovvero metodo 2 o 3 dell'articolo di riferimento).

Nell'utilizzarla, invece, in un altro progetto dove questa classe deve essere inclusa in diversi files ottengo sistematiche lamentele da parte del linker che mi dice che i simboli sono già definiti...

Dubito che sia utile postare del codice, perché l'errore mi sembra più che altro concettuale, quindi aspetto vostre dritte per bypassare lo stallo.

Grazie!
 
Registrato

I Moderatori invitano tutti gli utenti a prendere visione del REGOLAMENTO e a rispettarlo.
http://myitside.blogspot.com
Hyde
Global Moderator
Hero Member
*****

Karma: +47/-6
Scollegato Scollegato

Messaggi: 3266


I am a man who walks alone


Mostra profilo WWW
« Risposta #1 inserita:: Agosto 30, 2012, 11:27:46 am »

Ovviamente già so che definendo i membri template nell'header risolverò il mio problema, però vorrei trovare qualche soluzione robusta (sempre che esista) per mantenere definizione e dichiarazione divisi.
Registrato

I Moderatori invitano tutti gli utenti a prendere visione del REGOLAMENTO e a rispettarlo.
http://myitside.blogspot.com
shodan
Newbie
*

Karma: +2/-0
Scollegato Scollegato

Messaggi: 3


Mostra profilo
« Risposta #2 inserita:: Agosto 30, 2012, 12:41:36 pm »

Basta inserire inline davanti la definizione della funzione.
Es.
Codice:
template <typename T>
inline int Test( /* params */) {
    ...sviluppo...
}
Registrato
Hyde
Global Moderator
Hero Member
*****

Karma: +47/-6
Scollegato Scollegato

Messaggi: 3266


I am a man who walks alone


Mostra profilo WWW
« Risposta #3 inserita:: Agosto 30, 2012, 03:22:57 pm »

Shodan, inline non risolve i problemi del linker...
Registrato

I Moderatori invitano tutti gli utenti a prendere visione del REGOLAMENTO e a rispettarlo.
http://myitside.blogspot.com
shodan
Newbie
*

Karma: +2/-0
Scollegato Scollegato

Messaggi: 3


Mostra profilo
« Risposta #4 inserita:: Agosto 30, 2012, 05:35:02 pm »

Se alla fine di file.h includi file.cpp, di fatto le funzioni template sono definite in file.h
E le funzioni messe in un file.h (comprese le definizioni delle funzioni template) vanno dichiarate inline per non violare la One Definition Rule, cosa che riguarda proprio il linker.

Un link che spiega il problema è:
http://www.experts-exchange.com/Programming/Languages/CPP/A_1199-Seperating-C-template-declaration-and-implementation.html

Una FAQ sullo stesso argomento.
http://womble.decadent.org.uk/c++/template-faq.html#dup-instant
(il 13° punto)



Registrato
Hyde
Global Moderator
Hero Member
*****

Karma: +47/-6
Scollegato Scollegato

Messaggi: 3266


I am a man who walks alone


Mostra profilo WWW
« Risposta #5 inserita:: Agosto 30, 2012, 10:14:49 pm »

Grazie shodan per i links che mi hanno fornito un'utile spiegazione della teoria alla base dell'articolo presentato su CodeProject che avevo linkato in precedenza, ma il problema non è comunque risolto e forse è stato parzialmente spiegato male da me nel primo post.

Faccio un esempio pratico, così da tentare di spiegarmi meglio.

Codice:
// MyFileIni.h
#pragma once

#include <string>
#include <sstream>

class CMyFileIni
{
public:

CMyFileIni(void);
~CMyFileIni(void);

// scrive un valore generico in una determinata sezione del file ini
template<typename T>  bool WriteIni(myString section,myString key, T value,myString fpath);

// legge un determinato valore dal file ini
template<typename T>  bool ReadIni(myString section,myString key, T& value,myString fpath);

[...]
};

#include "MyFileIni.cpp"


L'implementazione di questa classe è tutta contenuta nell'apposito file cpp, così come la definizione della funzione template (non specializzazione).

Ne riporto un frammento

Codice:
#include "StdAfx.h"
#include "MyFileIni.h"

using namespace std;

CMyFileIni::CMyFileIni(void)
{

}

template<typename T> 
inline bool CMyFileIni::WriteIni(myString section,myString key, T value,myString fpath)
{
// blah blah...
}


Ora poniamo il cosa che io abbia 2 classi: ClassA e ClassB, con le loro belle coppie di header e cpp. ClassB è una classe che espone alcune funzioni che devono poter essere usate anche da alcuni metodi di ClassA, quindi nel file ClassA.cpp c'è questa inclusione

Codice:
#include "classb.h"
#include "MyFileIni.h"

ClassA usa anche la classe CMyFileIni ed il tutto viene compilato e linkato egregiamente (anche senza la necessità di inline).

Ora ipotizziamo che anche ClassB abbia necessità di usare CMyFileIni e quindi anche nel file ClassB.cpp avrò
Codice:
#include "MyFileIni.h"

A questo punto si scatena il linker con l'errore LNK2005, ovvero: symbol already defined in object
Registrato

I Moderatori invitano tutti gli utenti a prendere visione del REGOLAMENTO e a rispettarlo.
http://myitside.blogspot.com
shodan
Newbie
*

Karma: +2/-0
Scollegato Scollegato

Messaggi: 3


Mostra profilo
« Risposta #6 inserita:: Agosto 31, 2012, 12:13:17 am »

Se solo ClassA usa MyfileIni.h, non violi la One Definition Rule in quanto il compilatore pone il simbolo per il linker in solo un file, ma se MyFileIni.h lo includi in due diverse unità di compilazione, il compilatore porrà lo stesso simbolo in due diversi file.obj e il linker va in confusione.
La cosa è più evidente nei template in quanto si è obbligati a metterli in qualche modo negli header file, ma lo stesso problema si verifica se metti una funzione non template in un header file.

Nel frammento di codice postato non hai messo inline il costruttore e il distruttore, pertanto il linker si troverà due simboli uguali (ad esempio il costruttore) in due file diversi e darà errore. 
Come ho detto, se includi un file.qualcosa in un file.h tutto diventa file.h e quindi un header file. E tutte (ma proprio tutte) le funzioni (template e non) in un file header vanno specificate inline.
Quindi:
Codice:
inline CMyFileIni::CMyFileIni(void)
{

}

inline CMyFileIni::~CMyFileIni()
{

}
etc. 
Registrato
Hyde
Global Moderator
Hero Member
*****

Karma: +47/-6
Scollegato Scollegato

Messaggi: 3266


I am a man who walks alone


Mostra profilo WWW
« Risposta #7 inserita:: Agosto 31, 2012, 09:12:58 am »

Pardon shodan, ieri sera ero stato distratto e quindi non avevo giustamente definito inline anche gli altri metodi.
Ora il tutto è correttamente compilato/linkato.

A questo punto però credo che la soluzione più comoda (non so se sia anche la migliore da un punto di vista del linguaggio) è quella di non includere il file cpp all'interno dell'header, perché altrimenti devo escluderlo dal build del progetto, ma includerlo direttamente nel file dove andrò ad utilizzare quella classe.
In questo modo è possibile compilare singolarmente anche il cpp in caso di eventuali possibili future modifiche.

Grazie per il supporto!
Registrato

I Moderatori invitano tutti gli utenti a prendere visione del REGOLAMENTO e a rispettarlo.
http://myitside.blogspot.com
Pagine: [1]   Vai su
  Stampa  
 
Vai a:  

Copyright © 2011 Edizioni Master SpA. p.iva : 02105820787

Tutti i diritti di proprietà letteraria e artistica riservati. - Privacy



Links to Page