2013-02-26 15 views
7

Sto lavorando su una libreria statica e la libreria ha più modelli di classi e modelli di funzioni. Capisco per utilizzare i modelli all'interno della libreria statica tutto (dichiarazione/definizione) deve essere nel file di intestazione. Tuttavia, in questo caso particolare poiché conosco i tipi di specializzazione che pensavo di poter utilizzare in avanti, dichiaro invece la specializzazione.Libreria statica con modello di istanza

Questo trucco funziona bene con i modelli di classe (e le sue funzioni) e posso utilizzare tutta la funzione di libreria dal mio codice applicazione. Tuttavia, non appena mi presento modello di funzione libera all'interno della libreria e cerco di usare la funzione su modelli libera dal mio codice di applicazione mi dà errore di linker:

error LNK2019: unresolved external symbol "class TemplatedStaticLib __cdecl HelpingRegistration(int)" ([email protected]@@[email protected]@@[email protected]) referenced in function _main 1>C:\src\cpp\vs2008\StaticLibExample\MathFuncsLib\Debug\TemplatedStaticLibApp.exe : fatal error LNK1120: 1 unresolved externals" I am using VS2008, here is the code

// libreria statica file di intestazione (h)

#ifndef _TEMPLATED_STATIC_LIB_ 
#define _TEMPLATED_STATIC_LIB_ 

#include <iostream> 

template<typename T> 
class TemplatedStaticLib 
{ 
public: 
    TemplatedStaticLib(){}; 
    ~TemplatedStaticLib(){}; 

    void print(T t); 

}; 

template<typename T> 
TemplatedStaticLib<T> HelpingRegistration(T); 


#endif 

// libreria statica file di classe (cpp)

#include "TemplatedStaticLib.h" 

//Specialization 
template class TemplatedStaticLib<double>; 
template class TemplatedStaticLib<int>; 
template class TemplatedStaticLib<std::string>; 


template<typename T> 
void TemplatedStaticLib<T>::print(T t) 
{ 
    std::cout << "Templated Print " << typeid(t).name() << std::endl; 
} 

void HelpingRegistration(void) 
{ 
} 

//Specialization of free function 
template<> TemplatedStaticLib<int> HelpingRegistration<int>(int); 
template<> TemplatedStaticLib<double> HelpingRegistration<double>(double); 
template<> TemplatedStaticLib<std::string> HelpingRegistration<std::string>(std::string); 

template<typename T> 
TemplatedStaticLib<T> HelpingRegistration(T t) 
{ 
     std::cout << "Function Templated Print " << typeid(t).name() << std::endl; 
     return t; 
} 

// Il codice dell'applicazione

#include "TemplatedStaticLib.h" 

int main(int argc, char* argv[]) 
{ 
    int anInt = 99; 
    TemplatedStaticLib<int> test; 
    test.print(anInt);//works 

    double aDouble = 3.9; 
    TemplatedStaticLib<double> double_test; 
    double_test.print(aDouble); //works 

    std::string aString = "James"; 

    TemplatedStaticLib<std::string> string_test; 
    string_test.print(aString);//works 

    //The following lines gives linker error 
    HelpingRegistration(anInt); 
    HelpingRegistration(aDouble); 
    HelpingRegistration(aString); 


    return 0; 
} 

Non so perché sia ​​diverso e come posso risolvere questo problema. Qualsiasi aiuto è apprezzato.

+1

I modelli non possono essere definiti su unità di traduzione. – 0x499602D2

+0

classico esempio di abuso di modelli –

+0

Hmm Mi chiedo perché funzioni per caso modello di classe quindi? – jazaman

risposta

8

conto del fatto che questi sono non dichiarazioni in avanti, ma piuttosto istanze esplicite dei tuoi modelli di classe. Questo è ciò che consente di inserire la definizione in un file .cpp e di non ottenere alcun errore di riferimento non risolto da parte del linker, a condizione che nelle altre unità di traduzione vengano utilizzate solo le istanze del modello.

D'altra parte, questi:

template<> TemplatedStaticLib<int> HelpingRegistration<int>(int); 
template<> TemplatedStaticLib<double> HelpingRegistration<double>(double); 
template<> TemplatedStaticLib<std::string> HelpingRegistration<std::string>(std::string); 

sono dichiarazioni di specializzazioni esplicite di modelli di funzione. Quello che è più probabile che tu intenda fare è, invece, fornire le istanze esplicite . La sintassi per farlo è la seguente:

template TemplatedStaticLib<int> HelpingRegistration<>(int); 
template TemplatedStaticLib<double> HelpingRegistration<>(double); 
template TemplatedStaticLib<std::string> HelpingRegistration<>(std::string); 

Una volta che si rimediare, si vedrà che il compilatore in realtà instantiate il modello HelpingRegistration<>() funzione e sarà anche emettere un errore mentre si fa così, perché si sta tentando di convertire un int ad un oggetto di tipo TemplatedStaticLib<int> (resp TemplatedStaticLib<double> o TemplatedStaticLib<string>.), per i quali non è prevista la conversione (o almeno non mostrato nel codice che hai postato) (resp un double o string.):

template<typename T> 
TemplatedStaticLib<T> HelpingRegistration(T t) 
{ 
    std::cout << "Function Templated Print " << typeid(t).name() << std::endl; 
    return t; // CANNOT BE CONVERTED! 
} 

Correggere questo errore (ad es. facendo return TemplateStaticLib<T>();), il programma compilerà il collegamento e.

+0

Grazie mille per l'indizio @Andy, tutto ciò di cui avevo bisogno è l'istanziazione esplicita dei modelli di funzione non la Specializzazione esplicita e grazie per aver segnalato anche il problema di conversione. In realtà non ha bisogno di convertire affatto. così ho modificato il template di Specializzazione <> TemplatedStaticLib HelpingRegistration (int) al template void HelpingRegistration (int t) e tutto funziona come un incantesimo. – jazaman

+0

@jazaman: OK, felice di poter aiutare :-) –

Problemi correlati