I have been having link problems (see my previous post) and I got
around to trying one by one, different combinations since I absolutely
could not figure out why things weren't working. I have done exactly
the same type of thing before and it worked like a charm!

I got around to wondering finally if it could be a problem with the way
I have organized things.

Let's assume a template class declaration as follows:

template<typename DeallocType>
class DefaultDeallocator : public virtual Deallocator<DeallocType>
{

public:
DefaultDeallocator();
virtual ~DefaultDeallocator();

virtual void Delete(DeallocType*);
virtual void DeleteObjectArray(DeallocType*);
virtual void DeletePointerArray(DeallocType**, unsigned long);
};

This is in a header called DefaultDeallocator.h (duh! :)

I have the definition in a module called DefaultDeallocator.cpp.

template<typename DeallocType>
DefaultDeallocator<DeallocType>::DefaultDeallocator()
{
}

template<typename DeallocType>
DefaultDeallocator<DeallocType>::~DefaultDeallocator()
{
}

template<typename DeallocType>
void DefaultDeallocator<DeallocType>::Delete(DeallocType* obj)
{
if(NULL != obj)
{
delete obj;
}
}

template<typename DeallocType>
void DefaultDeallocator<DeallocType>
::DeleteObjectArray(DeallocType* array)
{
if(NULL != array)
{
delete[] array;
}
}

template<typename DeallocType>
void DefaultDeallocator<DeallocType>
::DeletePointerArray(DeallocType** ptrarray, unsigned
long num)
{
if(NULL != ptrarray &&
num > 0)
{
for(unsigned long i = 0; i < num; ++i)
{
delete ptrarray[i];
}
}
}

Could it be that because the definition is in a module as opposed to
being completely in the header itself, that I am getting unresolved
external link problems. Here are my errors:

Creating library Debug/SmartPointer2.lib and object
Debug/SmartPointer2.exp

Test.obj : error LNK2019: unresolved external symbol "public: virtual
__thiscall MCMDocumentCache::DefaultDeallocator<class
MCMDocumentCache::ReferenceCounter>::~DefaultDeallocator<class
MCMDocumentCache::ReferenceCounter>(void)"
(??1?$DefaultDeallocator@VReferenceCounter@MCMDocumentCache@@@MCMDocumentCache@@UAE@XZ)
referenced in function "void __cdecl
Test_Deallocator_Construction(void)"
(?Test_Deallocator_Construction@@YAXXZ)


Test.obj : error LNK2019: unresolved external symbol "public:
__thiscall MCMDocumentCache::DefaultDeallocator<class
MCMDocumentCache::ReferenceCounter>::DefaultDeallocator<class
MCMDocumentCache::ReferenceCounter>(void)"
(??0?$DefaultDeallocator@VReferenceCounter@MCMDocumentCache@@@MCMDocumentCache@@QAE@XZ)
referenced in function "void __cdecl
Test_Deallocator_Construction(void)"
(?Test_Deallocator_Construction@@YAXXZ)


Test.obj : error LNK2019: unresolved external symbol "public: virtual
void __thiscall MCMDocumentCache::DefaultDeallocator<class
MCMDocumentCache::ReferenceCounter>::Delete(class
MCMDocumentCache::ReferenceCounter *)"
(?Delete@?$DefaultDeallocator@VReferenceCounter@MCMDocumentCache@@@MCMDocumentCache@@UAEXPAVReferenceCounter@2@@Z)
referenced in function "void __cdecl Test_Deallocator_Delete(void)"
(?Test_Deallocator_Delete@@YAXXZ)


Test.obj : error LNK2019: unresolved external symbol "public: virtual
void __thiscall MCMDocumentCache::DefaultDeallocator<class
MCMDocumentCache::ReferenceCounter>::DeleteObjectArray(class
MCMDocumentCache::ReferenceCounter *)"
(?DeleteObjectArray@?$DefaultDeallocator@VReferenceCounter@MCMDocumentCache@@@MCMDocumentCache@@UAEXPAVReferenceCounter@2@@Z)
referenced in function "void __cdecl
Test_Deallocator_DeleteObjectArray(void)"
(?Test_Deallocator_DeleteObjectArray@@YAXXZ)


Test.obj : error LNK2019: unresolved external symbol "public: virtual
void __thiscall MCMDocumentCache::DefaultDeallocator<class
MCMDocumentCache::ReferenceCounter>::DeletePointerArray(class
MCMDocumentCache::ReferenceCounter * *,unsigned long)"
(?DeletePointerArray@?$DefaultDeallocator@VReferenceCounter@MCMDocumentCache@@@MCMDocumentCache@@UAEXPAPAVReferenceCounter@2@K@Z)
referenced in function "void __cdecl
Test_Deallocator_DeletePointerArray(void)"
(?Test_Deallocator_DeletePointerArray@@YAXXZ)


Debug/SmartPointer2.exe : fatal error LNK1120: 5 unresolved externals

If my supposition is correct, that kind of seems funny. Supposing I
were distributing a library and I didn't want to expose my
implementation, what would I do?

thanks,

-vijai.

Re: Defining template class member functions in a separate module by Vijai

Vijai
Sun Aug 21 21:11:22 CDT 2005

To augment my post,

I looked into the "stlport" sources. I saw that they have organized
things the way I did originally. To further test things out, I moved
the entire implementation into the header file (inline). Things work
perfectly now. I find this extremely curious. I am using VC 2003.

thanks,

-vijai.


Re: Defining template class member functions in a separate module by Vijai

Vijai
Sun Aug 21 22:15:24 CDT 2005

Well, I answered my own question after testing with GCC.

It seems that template functions and classes must be defined in the
header. A separate implementation in a module is allowed, provided this
module is included in the header.

-vijai.


Re: Defining template class member functions in a separate module by Victor

Victor
Sun Aug 21 22:31:52 CDT 2005

Vijai Kalyan wrote:
> Well, I answered my own question after testing with GCC.
>
> It seems that template functions and classes must be defined in the
> header. A separate implementation in a module is allowed, provided
> this module is included in the header.

Actually, using explicit instantiation you _can_ put implementations
in a separate file _and_ not include it. You limit yourself (and
your users) to a particular set of template arguments. See C++ FAQ
Lite for more information.

V



Re: Defining template class member functions in a separate module by Alex

Alex
Mon Aug 22 03:18:17 CDT 2005

Vijai Kalyan wrote:
> Let's assume a template class declaration as follows:
>
> [...]
>
> This is in a header called DefaultDeallocator.h (duh! :)
>
> I have the definition in a module called
> DefaultDeallocator.cpp.
>
> [...]
>
> Could it be that because the definition is in a module as
> opposed to being completely in the header itself, that I
> am getting unresolved external link problems.

Yes, it's precisely because of that. You get errors because
you're trying to use instantiation model, which isn't
supported by compiler.

There are two template instantiation models:

1. Inclusion model. In the inclusion model, a template must
be defined (or included) in a translation unit that
instantiates it before the point of instantiation.

2. Separation model. In the separation model, a template can
be defined in one translation unit and instantiated in
another (separate) translation unit.

In order to distinguish between instantiation models there
is 'export' C++ keyword.

"14 export Keyword on a Template"
http://msdn.microsoft.com/library/en-us/vclang/html/vclrf14ExportKeywordOnTemplate.asp

Currently only one implementation supports separation model:
Comeau C++ Compiler Fron-End.
(http://www.comeaucomputing.com/) Other compilers don't
support separation model [yet].

> Supposing I were distributing a library and I didn't want
> to expose my implementation, what would I do?

You can't do anything because templates are not code. So,
you can't compile them into separate binary. Actual code is
generated by compiler at template instantiation time. Even
with separation model you can't hide template definitions,
because you can't predict with which type user will
instantiate ypur template.



Re: Defining template class member functions in a separate module by Vijai

Vijai
Mon Aug 22 06:51:47 CDT 2005

Aha! Ok, great! Thanks for the info both Victor and Alex!

regards,

-vijai.


Re: Defining template class member functions in a separate module by Bo

Bo
Mon Aug 22 11:13:12 CDT 2005


"Alex Blekhman" <tkfx.N05P4M@yahoo.com> skrev i meddelandet
news:OPhDOIvpFHA.1048@tk2msftngp13.phx.gbl...
> There are two template instantiation models:
>
> 1. Inclusion model. In the inclusion model, a template must
> be defined (or included) in a translation unit that
> instantiates it before the point of instantiation.
>
> 2. Separation model. In the separation model, a template can
> be defined in one translation unit and instantiated in
> another (separate) translation unit.
>
> In order to distinguish between instantiation models there
> is 'export' C++ keyword.
>
> "14 export Keyword on a Template"
> http://msdn.microsoft.com/library/en-us/vclang/html/vclrf14ExportKeywordOnTemplate.asp
>
> Currently only one implementation supports separation model:
> Comeau C++ Compiler Fron-End.
> (http://www.comeaucomputing.com/) Other compilers don't
> support separation model [yet].
>

There are other compilers (using the same front end) that also
implement export, like this one from a well known company:

http://www.intel.com/cd/software/products/asmo-na/eng/compilers/219793.htm


Bo Persson



Re: Defining template class member functions in a separate module by Vijai

Vijai
Tue Aug 23 06:51:05 CDT 2005

Unfortunately, as part of a commerical firm, I don't have a choice as
to the compiler or the platform. But, the tips really helped!

thanks again,

-vijai.