Problem creating shared lib containing templates. Help......
hey guys, any help would be appreciated as this is driving me nuts.
I am basically trying to create a shared lib that contains templates. This code used to work on solaris under Sunwspro but when i try and compile under RH linux CC: Using built-in specs. Target: x86_64-redhat-linux Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-libgcj-multifile --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --with-cpu=generic --host=x86_64-redhat-linux Thread model: posix gcc version 4.1.2 20071124 (Red Hat 4.1.2-42) It doesn't work. Here is my code ( any help would be greatly appreciated ) //AClass.h #include <string> using namespace std; template <class T> class AClass { public: AClass(){}; ~AClass(){}; T getName(); private: T name; }; //AClass.cc #include "AClass.h" template <class T> T AClass<T>::getName() { return name; } //TestA.cc #include "AClass.h" int main() { AClass<string> a; a.getName(); return 0; } /usr/bin/cc -m32 -c -o AClass.o AClass.cc - COMPILES OK /usr/bin/cc -shared -o libTest.so AClass.o -g -m32 -lstdc++ - CREATES SHARED LIB Here is the nm map for the shared lib. Interestingly enough, no reference to getName() ?? nm libTest.so 00000000000013fc a _DYNAMIC 00000000000014d0 a _GLOBAL_OFFSET_TABLE_ w _Jv_RegisterClasses 00000000000013e8 d __CTOR_END__ 00000000000013e4 d __CTOR_LIST__ 00000000000013f0 d __DTOR_END__ 00000000000013ec d __DTOR_LIST__ 00000000000003e0 r __FRAME_END__ 00000000000013f4 d __JCR_END__ 00000000000013f4 d __JCR_LIST__ 00000000000014e4 A __bss_start w __cxa_finalize@@GLIBC_2.1.3 0000000000000390 t __do_global_ctors_aux 00000000000002d0 t __do_global_dtors_aux 00000000000013f8 d __dso_handle w __gmon_start__ 0000000000000387 t __i686.get_pc_thunk.bx 00000000000014e4 A _edata 00000000000014ec A _end 00000000000003c4 T _fini 0000000000000258 T _init 00000000000002a0 t call_gmon_start 00000000000014e8 b completed.5803 00000000000014e4 b dtor_idx.5805 0000000000000350 t frame_dummy /usr/bin/cc -g -m32 -Wno-deprecated -I. -L. -l Test -lstdc++ TestA.cc -o TestA.exe This fails with: /usr/bin/cc -g -m32 -Wno-deprecated -I. -L. -l Test -lstdc++ TestA.cc -o TestA.exe /var/tmp/cccRx1dy.o: In function `main': /home/mark/workspace/ITSMarketInfo/src/cpp/Sandbox/TestA.cc:5: undefined reference to `AClass<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >::getName()' collect2: ld returned 1 exit status |
What you're doing is not possible because templates aren't classes, functions, or data; they don't exist unless they're used. That means T AClass<T>::getName() doesn't exist until it's used, and it's never used in the context of the compilation of AClass.cc. For that reason, T AClass<T>::getName() must be available in the context of every parameter T being used, otherwise the function is never compiled. In other words, main.cc needs to include the file that defines T AClass<T>::getName(). Normally this is done by having the header include its own source, or by putting them both in the same file.
ta0kira |
Thanks, that worked a treat.
Interestingly enough my old implementation compiles / links and runs on Solaris. I do remember something about the Solaris Sunwspro compiler generating all of the template implemenations for you. |
All times are GMT -5. The time now is 09:03 PM. |