Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ How can I use template collections of template objects with inheritance?

Okay... first off I'm just going to explain something about what the architecture I'm after looks like. StatMgr

I am trying to implement a Stats Manager for my Stats objects. This stats manager is designed using templates (see declaration in the pic).The StatMgr holds a map (not STL) that maps a string implementation to a smart pointer (which is also a template), ARef. The specific sub-classes of StatMgr statically declare the template class of their parent StatMgr on construction (see LStatMgr and RStatMgr), and so themselves are not template classes.
This allows me to do things like:

LStatMgr myLStatMgr(10);
if(myLStatMgr.remove(acKey))
   cout << "Remove was good" << endl;
//No need to delete :)

OR

ARef<LStat> oLStat = NULL;
myLStatMgr.getNextStat(acKey,oLStat);
if(oLStat != NULL)
  oLStat->doSomethingLStatLike();

However that was before mister linker and madam compiler decided to join forces and thwart my attempts at progress (I still have to test the functionality and memory use!).
As it stands I have the following error and warning per stat class:

.\StatsMgr.cpp(740) : warning C4661: 'void StatsMgr::vPrint()' : no suitable definition provided for explicit template instantiation request
.\StatsMgr.cpp(740) : warning C4661: 'void StatsMgr::vPrint()' : no suitable definition provided for explicit template instantiation request
.\StatsMgr.cpp(104) : error C2084: function 'StatsMgr::StatsMgr(const enum doCollect,const int)' already has a body
.\StatsMgr.cpp(104) : error C2084: function 'StatsMgr::StatsMgr(const enum doCollect,const int)' already has a body

Now regarding the warnings :: at line 740 there are delarations as so:

template class StatsMgr<LStat>;
template class StatsMgr<RStat>;

I added this because if I don't do that then I end up with a mess of linker errors (see them below). However there ARE declarations and implementations of vPrint() in all of the Stat subclasses!

Regarding the errors: The base class "StatsMgr" has a defined COTR, as do the subclasses (LStatMgr & RStatMgr). Why does the inheritance not simply sort this out? Obviously this is something to do with the explicit template instances at the end of the CPP but I cannot understand what exactly is going on.
Below is from StatsMgr.cpp

template<class type>
StatsMgr<type>::StatsMgr(const doCollect eOption, const int nListSize) :
    oMyMap(wHashString, nListSize), oMyMapIter(oStatsList)
{
    m_eCollectionOption = eOption;
}

Below is from LStatMgr.cpp

LStatMgr::LStatMgr(const doCollect eOption, const int nListSize) :
StatsMgr<LStat> (eOption, nListSize)
{
}

I tried substituting

class LStatMgr;
class RStatMgr;

for the template declarations and this gets passed the compile errors but then the linker cannot find any non-overridden functions. For example if I have a function in StatMgr called "getNextStat()" and override that in RStatMgr but not in LStatMgr, then the linker complains about that. Why is inheritance not covering this situation?



It makes me sad. I may have to fall back to composition (which should be preferred, but not in this situation).
By the way... I am compiling with MSVC++ 4.1 (!!!), so I understand if you cannot duplicate, but please help.
Thanks,
Dennis. (sorry about the very long post)

like image 510
Dennis Avatar asked Nov 05 '22 05:11

Dennis


1 Answers

Put template code directly in the header, not in a separate CPP file.

See this previous question for background.

EDIT: btw I see you are on a very old compiler - this problem may be insurmountable, even VC6 was sketchy for templates.

like image 157
Steve Townsend Avatar answered Nov 09 '22 05:11

Steve Townsend