By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
444,058 Members | 1,209 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 444,058 IT Pros & Developers. It's quick & easy.

Linker problem with templated function

P: 29
The following is an abridged copy of the code I am using in a template function along with the linker error produced during the build. The compiler has no issues with the code, only the linker:

file DB.h
Expand|Select|Wrap|Line Numbers
  1.  
  2. enum TypeEnum
  3.    {
  4.       eDouble,
  5.       eInteger,
  6.       eBool,
  7.       eString,
  8.       eFloat,
  9.       eLong,
  10.       TypeEnumRange
  11.    };
  12.  
  13. template <class T>
  14. class DataBusGenericOutputType
  15. {
  16.       public:
  17.  
  18.          DataBusGenericOutputType();
  19.  
  20.          void    SetValue(T data){ GT->SetValue(data); } ;
  21.  
  22.       private:
  23.  
  24.          DataBusGenericType<T>* GT;
  25. };
  26.  
  27. class DataBus
  28. {
  29.    public:
  30.  
  31.    ......
  32.  
  33.       template <typename T> DataBusGenericOutputType<T> *Register2(std::string ID, TypeEnum type, T value);
  34.  
  35.    ......
  36.  
  37.    private:
  38.  
  39.    ......
  40.  
  41.         std::list< DataBusGenericType<double> >  DoubleList;
  42.         std::list< DataBusGenericType<string> >  StringList;
  43.         std::list< DataBusGenericType<int>    >  IntList;
  44.         std::list< DataBusGenericType<bool>   >  BoolList;
  45.         std::list< DataBusGenericType<float>  >  FloatList;
  46.         std::list< DataBusGenericType<long>   >  LongList;
  47.  
  48.    ......
  49. };
  50.  
file DB.cpp
Expand|Select|Wrap|Line Numbers
  1. template <typename T> 
  2. DataBusGenericOutputType<T> *DataBus::Register2(std::string ID, TypeEnum type, T value)
  3. {
  4.    DataBusGenericOutputType<T> *OutType = NULL;
  5.    DataBusGenericType<T>       *GenType = NULL;
  6.    std::vector<string> IDparts;
  7.  
  8.    IDparts = ParseID(ID); 
  9.  
  10.    GenType = new DataBusGenericType<T>(IDparts[ClassLocation], IDparts[VariableLocation], IDparts[TypeLocation], type, value);
  11.  
  12.    switch(type)
  13.    {
  14.       case eDouble:
  15.            DoubleList.push_back(*GenType);
  16.            OutType = new DataBusGenericOutputType<T>(&DoubleList.back());
  17.            break;
  18.  
  19.       case eInteger:
  20.            IntList.push_back(*GenType);
  21.            OutType = new DataBusGenericOutputType<T>(&IntList.back());
  22.            break;
  23.  
  24.       case eBool:
  25.            BoolList.push_back(*GenType);
  26.            OutType = new DataBusGenericOutputType<T>(&BoolList.back());
  27.            break;
  28.  
  29.       case eString:
  30.            StringList.push_back(*GenType);
  31.            OutType = new DataBusGenericOutputType<T>(&StringList.back());
  32.            break;
  33.  
  34.       case eFloat:
  35.            FloatList.push_back(*GenType);
  36.            OutType = new DataBusGenericOutputType<T>(&FloatList.back());
  37.            break;
  38.  
  39.       case eLong:
  40.            LongList.push_back(*GenType);
  41.            OutType = new DataBusGenericOutputType<T>(&LongList.back());
  42.            break;
  43.  
  44.       default: 
  45.            break;
  46.  
  47.    }
  48.    return OutType;
  49. }
  50.  
file Dummy.cpp
Expand|Select|Wrap|Line Numbers
  1. #include "DB.h"
  2.  
  3. void Dummy::Register()
  4. {
  5.    DataBus *DB = new DataBus();
  6.    double mDummyDouble;
  7.    DataBusGenericOutputType<double> *oDummyDouble;
  8.  
  9. oDummyDouble = DB->Register2("Dummy.DummyDouble.double", eDouble, mDummyDouble); // <---This is line 115 which the linker error references
  10.  
  11. ....
  12. }
  13.  

Error from the linker:
./Lib/libBigBastard.a(Dummy.o)(.text+0x6e6): In function `Dummy::Register()':
/home/jr/Dummy.cpp:115: undefined reference to `DataBusGenericOutputType<double>* DataBus::Register2<double>(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, TypeEnum, double)'

Again, the compiler gives no errors so all local and stl headers have been properly included and all functions and types seem to be accessible by the code. For what it's worth, the code is being built using gcc version 3.2.2.

Thanks!
Jul 21 '08 #1
Share this Question
Share on Google+
7 Replies


Savage
Expert 100+
P: 1,764
That function is not a class method.It's outside of DataBusGenericOutputType class scope..
Jul 21 '08 #2

P: 29
That function is not a class method.It's outside of DataBusGenericOutputType class scope..
I apologize for that, in my rush to post the question I did not clearly specify the class declaration. Please see the edited original post again.

Thanks!
Jul 21 '08 #3

Savage
Expert 100+
P: 1,764
I apologize for that, in my rush to post the question I did not clearly specify the class declaration. Please see the edited original post again.

Thanks!
Template functions must be defined in the same file where they are declared.

NOTE:

There are ways around it like using export keyword or including a cpp file with function definitions just after template class declarations,but they can really complicate your life.Export templates keyword is not supported in all compilers and including a definition cpp file can create mess in your project organization.
Jul 21 '08 #4

P: 29
Template functions must be defined in the same file where they are declared.

NOTE:

There are ways around it like using export keyword or including a cpp file with function definitions just after template class declarations,but they can really complicate your life.Export templates keyword is not supported in all compilers and including a definition cpp file can create mess in your project organization.
Thanks! moving the definition did help. However, it turns out that the compiler doesn't like the use of the template type inside the switch statements so this code is not good anyway... On to a different approach.
Jul 22 '08 #5

weaknessforcats
Expert Mod 5K+
P: 9,197
There are ways around it like using export keyword
Quick tell me the name of any compiler that supports this. I have been telling my students there are no such compilers. Maybe I need an update.
Jul 22 '08 #6

Savage
Expert 100+
P: 1,764
Quick tell me the name of any compiler that supports this. I have been telling my students there are no such compilers. Maybe I need an update.
I'm not sure if Intel's 7.x compiler does support it,but I'm sure Comeau does.

Not very wide support indeed, making export for templates pretty useless.
Jul 22 '08 #7

Expert 100+
P: 671
Not very wide support indeed, making export for templates pretty useless.
Support or not, export for templates is very useless. Read up on Google on the problem with export. It does not work like you think it does.
Jul 22 '08 #8

Post your reply

Sign in to post your reply or Sign up for a free account.