|
Prev: Explicit casts to user-defined types
Next: Composition
From: JSeb on 7 Apr 2008 01:43 > Requiring the programmer to provide a full definition gives you full > control on the specialization, in the sense that not only you can add or > replace features, you can also remove them. But what if I want to reuse them? Suppose CTemplateClass<T> contains a gazillion methods; will I have to redeclare/redefine them all in CTemplateClass<T*> ? From my current understanding, the answer would be yes: even if CTemplateClass<T>::FooBar() and CTemplateClass<T*>::FooBar() are identical, FooBar has to be defined in both class templates... Wouldn't there be another way, that wouldn't require me to maintain a class template and its specialization "in sync"? Should I look towards class template INHERITANCE? Thank you so much for your answer! > PS: exercise for the reader: give the OP's definitions, what is the > destructor of CTemplateClass<T*>? CTemplateClass<T>::~CTemplateClass() { delete this->mpData; } CTemplateClass<T*>::~CTemplateClass() { // Show some manners! //delete this->mpData; } -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: JSeb on 7 Apr 2008 23:06 Okay: here's what I came up with, after your much appreciated comments. Instead of a helper class, I'm trying to use a common base class for the main template, and its specialization. Any comment will be much appreciated! Thanks again. ========================== // *** COMMON BASE CLASS *** template <typename T> class ATemplateClassCommonInterface { protected: const T* const mpData; int mCounter; protected: ATemplateClassCommonInterface(const T* apData, int aCounter = 0) : mpData(apData), mCounter(aCounter) { } public: virtual ~ATemplateClassCommonInterface() { } // COMMON INTERFACE --- TO BE IMPLEMENTED IN DERIVED TEMPLATES virtual void specializedMethod() = 0; // COMMON INTERFACE --- IMPLEMENTED HERE void commonMethod() { std::cout << "commonMethod : mCounter = " << this->mCounter << std::endl; this->mCounter++; } }; // *** MAIN CLASS TEMPLATE *** template <typename T> class CTemplateClass : public ATemplateClassCommonInterface<T> { public: CTemplateClass(const T& aData) : ATemplateClassCommonInterface<T>(new T(aData), 0) { std::cout << "CTemplateClass<T>::CTemplateClass : *mpData = " << *(this->mpData) << std::endl; } virtual ~CTemplateClass() { delete this->mpData; } void specializedMethod() { std::cout << "CTemplateClass<T>::specializedMethod" << std::endl; } }; // *** SPECIALIZED CLASS TEMPLATE *** template <typename T> class CTemplateClass<T*> : public ATemplateClassCommonInterface<T> { public: CTemplateClass(const T* apData) : ATemplateClassCommonInterface<T>(apData, 10) { std::cout << "CTemplateClass<T*>::CTemplateClass : *mpData = " << *(this->mpData) << std::endl; } virtual ~CTemplateClass() { // Show some manners. //delete this->mpData; } void specializedMethod() { //AHelper_TemplateClass<T>::specializedMethod(this); std::cout << "CTemplateClass<T*>::specializedMethod" << std::endl; } }; ========================== In the Main function, CTemplateClass<int>* pTC1 = new CTemplateClass<int>(10); CTemplateClass<int*>* pTC2 = new CTemplateClass<int*>(new int(15)); pTC1->commonMethod(); pTC2->commonMethod(); pTC1->specializedMethod(); pTC2->specializedMethod(); delete pTC1; delete pTC2; Output: CTemplateClass<T>::CTemplateClass : *mpData = 10 CTemplateClass<T*>::CTemplateClass : *mpData = 15 commonMethod : mCounter = 0 commonMethod : mCounter = 10 CTemplateClass<T>::specializedMethod CTemplateClass<T*>::specializedMethod -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Alberto Ganesh Barbati on 10 Apr 2008 06:13
JSeb ha scritto: >> Requiring the programmer to provide a full definition gives you full >> control on the specialization, in the sense that not only you can add or >> replace features, you can also remove them. > > But what if I want to reuse them? > > Suppose CTemplateClass<T> contains a gazillion methods; will I have to > redeclare/redefine them all in CTemplateClass<T*> ? Yes. > From my current understanding, the answer would be yes: even if > CTemplateClass<T>::FooBar() and CTemplateClass<T*>::FooBar() are > identical, FooBar has to be defined in both class templates... Correct. > Wouldn't there be another way, that wouldn't require me to maintain a > class template and its specialization "in sync"? Should I look towards > class template INHERITANCE? > If you want to factor code common to all specializations, you can use a base class, for example: template <class T> class CTemplateClassCommon { /* common part */ }; template <class T> class CTemplateClass : public CTemplateClassCommon<T> { /* main template */ }; template <class T> class CTemplateClass<T*> : public CTemplateClassCommon<T*> { /* specialization */ }; > >> PS: exercise for the reader: give the OP's definitions, what is the >> destructor of CTemplateClass<T*>? > > CTemplateClass<T>::~CTemplateClass() > { > delete this->mpData; > } > CTemplateClass<T*>::~CTemplateClass() > { > // Show some manners! > //delete this->mpData; > } > Gotcha! The right answer is that, given the OP's definition, the destructor of CTemplateClass<T*> is trivial. That's because you didn't declare it (the declaration in CTemplateClass<T> doesn't count!) and the class has neither bases nor data members. It's illegal to explicitly provide an implementation of a trivial destructor, as the compiler implicitly generates it for you. Notice, in particular, that while the destructor of CTemplateClass<T> is virtual, the destructor of CTemplateClass<T*> isn't. Because of that, CTemplateClass<T> is polymorphic and CTemplateClass<T*> isn't. HTH, Ganesh -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |