From: JSeb on
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
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
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
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
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! ]

 |  Next  |  Last
Pages: 1 2
Prev: Explicit casts to user-defined types
Next: Composition