Class Template throws "unresolved externals"

Started by
4 comments, last by directNoob 17 years ago
Hi. I made a class template for a scene, called

template< typename T >
class CScene
{
. . .
} ;

Then, in Main.h, I declared a pointer to this class template, like this:

CScene< ISolarSystem > *pMilkyScene ;

Then in Main.cpp, I give memory to the pointer to the class template:

pMilky = new CMilkyWay() ;
pMilkyScene = new CScene< ISolarSystem > ;

pMilky is a pointer of the type ISolarSystem and CMilkyWay is a class derived from ISolarSystem. Then, after the preceeding definitions, I assign the pMilky to the class template pointer, like this:

pMilkyScene->Initialize( "Solar System" ) ;
pMilkyScene->AppendObject( pMilky ) ;

This seems not to work, because I get the following:
Quote: 1>Main.obj : error LNK2019: unresolved external symbol "public: bool __thiscall CScene<class ISolarSystem>::AppendObject(class ISolarSystem * &)" (?AppendObject@?$CScene@VISolarSystem@@@@QAE_NAAPAVISolarSystem@@@Z) referenced in function "void __cdecl SpecialKeys(int,int,int)" (?SpecialKeys@@YAXHHH@Z) 1>Main.obj : error LNK2019: unresolved external symbol "public: bool __thiscall CScene<class ISolarSystem>::Initialize(char *)" (?Initialize@?$CScene@VISolarSystem@@@@QAE_NPAD@Z) referenced in function "void __cdecl SpecialKeys(int,int,int)" (?SpecialKeys@@YAXHHH@Z) 1>Main.obj : error LNK2019: unresolved external symbol "public: bool __thiscall CScene<class ISolarSystem>::Release(void)" (?Release@?$CScene@VISolarSystem@@@@QAE_NXZ) referenced in function "public: __thiscall CScene<class ISolarSystem>::~CScene<class ISolarSystem>(void)" (??1?$CScene@VISolarSystem@@@@QAE@XZ) 1>D:\D_Programming\D_P_FH\Semester2\Cg\Pr01\Praktikum01\Debug\Praktikum01.exe : fatal error LNK1120: 3 unresolved externals
Those functions are defined within CScene.cpp like :

...

template< typename T >
bool CScene< T >::AppendObject( T* &rObj )
{
   m_pSceneObjects->push_back( &rObj ) ;
   return true ;
}
...


Has anybody any idea what could be wrong??? Grateful Alex
Advertisement
Template implementation needs to go in the template header (it can go underneath the class, it doesn't have to be inlined).

This is due to the way compilers need to see the template to generate the code. In future, more compilers may allow the "export" keyword, which will allow you to put template code in a source file.
Quote:Original post by rip-off
In future, more compilers may allow the "export" keyword, which will allow you to put template code in a source file.


That's unlikely. The one single vendor (EDG) that produced a compiler with full support for the export keyword says it doesn't work the way people expect, it's difficult or impossible to get absolutely correct, and does not lend any real advantage. There has been a lot of talk on the standards committee about removing that feature from the language entirely.

The accepted solution is to either (1) put the entire template definition in a header file and rely on precompiled headers if build speed is a problem, or (2) place non-inline template definitions in a separate header file than is the template declaration, and include both headers in a .cpp file and explicitly instantiate the template. The latter solution is less flexible but more desireable when a limited deomain of template arguments is expected.

--smw

Stephen M. Webb
Professional Free Software Developer

Hi.

Thanks!

But there is even a third method, but is similar to the second described by
Bregma .

I put the declaration of the class in the header file CScene.h.
The definition, I put, as expaced, into a .cpp file, namely CScene.cpp.
In main.h then, I included the CScene.cpp file instead of CScene.h.
This works. I have forgotten about the thing with the cpp file...

I think this method is quite comfortable or do you have any other opinion?!


Thanks
Alex
Quote:Original post by directNoob
Hi.

Thanks!

But there is even a third method, but is similar to the second described by
Bregma .

I put the declaration of the class in the header file CScene.h.
The definition, I put, as expaced, into a .cpp file, namely CScene.cpp.
In main.h then, I included the CScene.cpp file instead of CScene.h.
This works. I have forgotten about the thing with the cpp file...

I think this method is quite comfortable or do you have any other opinion?!


Thanks
Alex


Well, an IDE will probably put the source file in the build list, then waste some time dealing with it when there is no non-template code in it. But I have seen the same idea done differently, like having template_foo.h and template_foo_impl.h and #including the second in the first.
Yes, this is a good idea when you want to constantly including .h files, I think.

Thanks again.
Alex

This topic is closed to new replies.

Advertisement