|
Prev: Explicit casts to user-defined types
Next: Composition
From: JSeb on 5 Apr 2008 23:59 Good afternoon, gurus and others! I have a template class that looks like this: template <typename T> class CTemplateClass { private: const T* const mpData; public: CTemplateClass<T>(const T& aData) : mpData(new T(aData)) { } virtual ~CTemplateClass<T>() { delete this->mpData; } }; I want to write a SPECIALIZED CONSTRUCTOR to deal with pointer types. >From what I found online, I should write something like that AFTER the code above: template <typename T> class CTemplateClass<T*> { public: CTemplateClass<T*>(const T* apData) : mpData(apData) { } }; But :^( the compiler tells me that CTemplateClass<T*> has no field named "mpData". I'm not too familiar with templates, and I don't quite understand the syntax involved in the specialization. To me, it looks as if "CTemplateClass" is defined twice, with the second definition indeed lacking the attribute "mpData". I don't get it : if "CTemplateClass<T*>" is a specialization. doesn't it have access to "CTemplateClass<T>" attributes and methods? (I know the answer is "no", but I fail to see why. In fact, from what I've read, both templates don't even need to share any interface). By the way, if I define "mpData" in the specialization as in the original template, it works. Well, I would appreciate if any of you could help me see more clearly through this. Or if you have any other approach to specialize the constructor for pointers, maybe it would make more sense to me! Thanks! -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Lance Diduck on 6 Apr 2008 08:59 On Apr 6, 10:59 am, JSeb <JSebBol...(a)gmail.com> wrote: > Good afternoon, gurus and others! > By the way, if I define "mpData" in the specialization as in the > original template, it works. > > Well, I would appreciate if any of you could help me see more clearly > through this. Or if you have any other approach to specialize the > constructor for pointers, maybe it would make more sense to me! > > Thanks! This is exactly correct. YOu cannot specialize a ctor, you can only overload them. CTemplateClass<T>(const T* aData) : mpData((aData)){} perhap may have compiled, but it is hardly what you were after-- then if T really were a pointer type, then you would have had to invoke this ctor by making a "pointer to a pointer." So creating what looks like a whole new template to deal with teh case T is a pointer (called a "partial specialization") is the correct approach. Lance -- [ 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 6 Apr 2008 09:24 JSeb ha scritto: > Good afternoon, gurus and others! > > I have a template class that looks like this: > > template <typename T> > class CTemplateClass > { > private: > const T* const mpData; > public: > CTemplateClass<T>(const T& aData) : mpData(new T(aData)) { } > virtual ~CTemplateClass<T>() > { > delete this->mpData; > } > }; You don't need to use CTemplateClass<T> inside the template body. CTemplateClass will just do. > I want to write a SPECIALIZED CONSTRUCTOR to deal with pointer types. > >>From what I found online, I should write something like that AFTER the > code above: > > template <typename T> > class CTemplateClass<T*> > { > public: > CTemplateClass<T*>(const T* apData) : mpData(apData) { } Again: CTemplateClass will do, here. Don't be fooled by the CTemplateClass<T*> after "class" above, which instead is required. > }; > > But :^( the compiler tells me that CTemplateClass<T*> has no field > named "mpData". That's correct: you didn't provide a declaration for it and you should have done it. > I'm not too familiar with templates, and I don't quite understand the > syntax involved in the specialization. To me, it looks as if > "CTemplateClass" is defined twice, with the second definition indeed > lacking the attribute "mpData". A specialization is a completely new definition, which does not have access to the "main" definition. The only relation between a template and one of its specialization is the name. Nothing else. This may seems strange, but, think about it... how could it be otherwise? How could the compiler decide that the line: CTemplateClass<T*>(const T* apData) : mpData(apData) { } in the specialization is meant to be a replacement of CTemplateClass<T>(const T& aData) : mpData(new T(aData)) { } in the main template? The two functions have completely different and unrelated signatures! If you were right and the specialization had access to the main template, then you would end up with two constructors, namely: CTemplateClass(T* const& aData) : mpData(new T(aData)) { } CTemplateClass(const T* apData) : mpData(apData) { } Notice that the first one takes a const reference to a pointer to T, which is completely different from the second, which takes a pointer to const T. (Be careful about where the const goes!) 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. And last but not least, you are even free to omit the main definition! For example, this idiom is perfectly valid and can sometime be useful: template <class T> class MyTemplate; // declared but not defined template <class T> class MyTemplate<T*> { // definition here }; > I don't get it : if "CTemplateClass<T*>" is a specialization. doesn't > it have access to "CTemplateClass<T>" attributes and methods? (I know > the answer is "no", but I fail to see why. In fact, from what I've > read, both templates don't even need to share any interface). The answer is no because CTemplateClass<T> and CTemplateClass<T*>, except for (part of) the name, they are totally unrelated types. > By the way, if I define "mpData" in the specialization as in the > original template, it works. Sure it does. HTH, Ganesh PS: exercise for the reader: give the OP's definitions, what is the destructor of CTemplateClass<T*>? -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Craig Scott on 7 Apr 2008 01:00 On Apr 7, 12:59 am, JSeb <JSebBol...(a)gmail.com> wrote: > Good afternoon, gurus and others! > > I have a template class that looks like this: > > template <typename T> > class CTemplateClass > { > private: > const T* const mpData; > public: > CTemplateClass<T>(const T& aData) : mpData(new T(aData)) { } > virtual ~CTemplateClass<T>() > { > delete this->mpData; > } > > }; > > I want to write a SPECIALIZED CONSTRUCTOR to deal with pointer types. > > >From what I found online, I should write something like that AFTER the > > code above: > > template <typename T> > class CTemplateClass<T*> > { > public: > CTemplateClass<T*>(const T* apData) : mpData(apData) { } > > }; > > But :^( the compiler tells me that CTemplateClass<T*> has no field > named "mpData". Your code specializes the class, not the constructor. More correctly, you are defining a *partial* specialization of the class. What you are looking for is a partial specialization of the constructor only, but the language doesn't support that directly. A common workaround for function templates and member function templates is to make the function call a separate static function within a class template and then partially specialize that class template. But since you want to have this behavior for a constructor, you won't be able to get the behavior you want because the technique will not consider the data member initializers (ie the initialization of mpData in your case) and your data member is const, so it cannot be changed after initialization which precludes changing it in the constructor body. For instruction, you could fully specialize the constructor for pointers to some known type, eg int* like so: template<> CTemplateClass<int*>::CTemplateClass(const int*& aData) : mpData(aData) { } If you didn't have const data members, you could use the technique I mentioned above: template <typename T> class Helper { public: static void doStuff(CTemplateClass<T>& c, T const& t) { // Default implementation goes here } }; template<typename T> class Helper<T*> { public: static void doStuff(CTemplateClass<T*>& c, T* const& t) { // Partially specialized implementation when T is a pointer type } }; template <typename T> class CTemplateClass { //const T* const mpData; // Cannot use const data for this technique public: CTemplateClass<T>(const T& aData) { Helper<T>::doStuff(*this, aData); } // ... other functions omitted }; You could probably get around the restriction on using const data members with a const_cast but personally I prefer to avoid such things if I can. -- Computational Modeling, CSIRO (CMIS) Melbourne, Australia [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Carl Barron on 7 Apr 2008 01:13
JSeb <JSebBolduc(a)gmail.com> wrote: > 'm not too familiar with templates, and I don't quite understand the > syntax involved in the specialization. To me, it looks as if > "CTemplateClass" is defined twice, with the second definition indeed > lacking the attribute "mpData". > > I don't get it : if "CTemplateClass<T*>" is a specialization. doesn't > it have access to "CTemplateClass<T>" attributes and methods? (I know > the answer is "no", but I fail to see why. In fact, from what I've > read, both templates don't even need to share any interface). A specialised templated class is a new type. It does not share anything except the name of the template with the general template. You need to duplicate the common stuff or possibly use inheritance to avoid the copying. This is more "has a" than "is a" so private inheritance with friendship or using clauses best describss it, although if there is little or no classical oop then public inheritance would work as long as you don't pass references or pointers to the base class. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |