473,385 Members | 1,838 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Why isn't this template being instantiated?

This code get's a link error (I'm guessing because the template isn't being
instantiated)...

// For using templates to simplify deleting items
template <class T>
// Returns the next ADHL in the list
AbstractDataHolderList*
// Used to delete this object and the item it points to
AbstractDataHolderList::DeleteThisItem(void)
{
// do stuff to update list (since this item is being removed)

delete (typename T*)m_thisItem;
delete this;

return m_nextADHL;
}

/* ... */ main (/* ... */)
{
/*****************************************
* We make some items (CString in this case?)
* and add em to the list, then run the program up here
*****************************************/

// This part is the important thing
while (myADHL != NULL)
myADHL = myADHL->DeleteThisItem<CString>();

return 0;
}

If I change the DeleteThisItem method in the ADHL class to be the
instanciated template for a CString (ie:
"/*...*/::DeleteThisItem<CString>(void)"), then there isn't a linking error.
But I'm wondering why the compiler doesn't notice that main is calling the
template with a forced type of CString. Shouldn't the call in main force an
instanciation of the template with T = CString? (as a side note... since
there are no parameters, if <CString> is omited in the DeleteThisItem call,
then this code doesn't even compile, because the type cannot be
determined... which is why i'm wondering, when I say that the type is a
CString, why isn't the CString version of the template created?)
Jul 22 '05 #1
8 1429
de*****@hotmail.com wrote:
This code get's a link error (I'm guessing because the template isn't being
instantiated)...

// For using templates to simplify deleting items
template <class T>
// Returns the next ADHL in the list
AbstractDataHolderList*
// Used to delete this object and the item it points to
AbstractDataHolderList::DeleteThisItem(void)
{
// do stuff to update list (since this item is being removed)

delete (typename T*)m_thisItem;
delete this;

return m_nextADHL;
}

/* ... */ main (/* ... */)
{
/*****************************************
* We make some items (CString in this case?)
* and add em to the list, then run the program up here
*****************************************/

// This part is the important thing
while (myADHL != NULL)
myADHL = myADHL->DeleteThisItem<CString>();

return 0;
}

If I change the DeleteThisItem method in the ADHL class to be the
instanciated template for a CString (ie:
"/*...*/::DeleteThisItem<CString>(void)"), then there isn't a linking error.
But I'm wondering why the compiler doesn't notice that main is calling the
template with a forced type of CString. Shouldn't the call in main force an
instanciation of the template with T = CString? (as a side note... since
there are no parameters, if <CString> is omited in the DeleteThisItem call,
then this code doesn't even compile, because the type cannot be
determined... which is why i'm wondering, when I say that the type is a
CString, why isn't the CString version of the template created?)


The name CString suggests that you're using Visual C++. Is it by any
chance VC++ v6? Then you need a work-around:

template <class T>
// Returns the next ADHL in the list
AbstractDataHolderList*
// Used to delete this object and the item it points to
AbstractDataHolderList::DeleteThisItem(T* = 0)

By introducing the argument of the same type as you're trying to get the
template to use you can trick the compiler into recognising the need to
instantiate the template correctly.

I am not actually sure about this work-around, do check with the VC++
newsgroup: microsoft.public.vc.language.

Victor
Jul 22 '05 #2
> The name CString suggests that you're using Visual C++. Is it by any
chance VC++ v6? Then you need a work-around:

template <class T>
// Returns the next ADHL in the list
AbstractDataHolderList*
// Used to delete this object and the item it points to
AbstractDataHolderList::DeleteThisItem(T* = 0)

By introducing the argument of the same type as you're trying to get the
template to use you can trick the compiler into recognising the need to
instantiate the template correctly.

I am not actually sure about this work-around, do check with the VC++
newsgroup: microsoft.public.vc.language.

Victor


Thanks for the info... so I guess in gcc, and other compilers this isn't
necessarily an issue? Other compilers figure this stuff out for me? (mines
..NET... so I guess m$ hasn't tried fixing this yet...) I just ended up doing
this:

template < >
// Returns the next ADHL in the list
AbstractDataHolderList*
// Used to delete this object and the CString item it points to
AbstractDataHolderList::DeleteThisItem < CString > (void)

for each type that I need to delete, as an added bonus I add one for "void"
which doesn't delete the item... just incase I find good reason to do
that... Well... if it's a VC++ ... feature ... 0.o then i'll just member
that I'm smart and they... are... well... thier smart too... but... I'm
SMARTER! ;)

Thanks,
Dead RAM
Jul 22 '05 #3
de*****@hotmail.com wrote:
The name CString suggests that you're using Visual C++. Is it by any
chance VC++ v6? Then you need a work-around:

template <class T>
// Returns the next ADHL in the list
AbstractDataHolderList*
// Used to delete this object and the item it points to
AbstractDataHolderList::DeleteThisItem(T* = 0)

By introducing the argument of the same type as you're trying to get the
template to use you can trick the compiler into recognising the need to
instantiate the template correctly.

I am not actually sure about this work-around, do check with the VC++
newsgroup: microsoft.public.vc.language.

Victor

Thanks for the info... so I guess in gcc, and other compilers this isn't
necessarily an issue? Other compilers figure this stuff out for me? (mines
.NET... so I guess m$ hasn't tried fixing this yet...) I just ended up doing
this:

template < >
// Returns the next ADHL in the list
AbstractDataHolderList*
// Used to delete this object and the CString item it points to
AbstractDataHolderList::DeleteThisItem < CString > (void)

for each type that I need to delete, as an added bonus I add one for "void"
which doesn't delete the item... just incase I find good reason to do
that... Well... if it's a VC++ ... feature ... 0.o then i'll just member
that I'm smart and they... are... well... thier smart too... but... I'm
SMARTER! ;)


I may have misinterpreted the situation, sorry about that. The .NET (is
that 7.1?) compiler is far more advanced than v6 when the templates are
concerned.

Since you didn't post the complete code, I couldn't verify the error on
any of the compilers available to me here, so I probably fell into
assuming too much. Try this:
----------------------------------
struct CS {}; // my version of "CString"
struct A { // my version of your "AbstractDataHolderList"
template<class T> A* foo(); // my "DeleteThisItem"
};

template<class T> A* A::foo() { // definition
T t;
return this;
}

int main() {
A a;
A* pa = &a;
pa = pa->foo<CS>();
}
----------------------------------
It compiles (and links) fine with my copy of VC++ v7.1.

Victor
Jul 22 '05 #4
> I may have misinterpreted the situation, sorry about that. The .NET (is
that 7.1?) compiler is far more advanced than v6 when the templates are
concerned.

Since you didn't post the complete code, I couldn't verify the error on
any of the compilers available to me here, so I probably fell into
assuming too much. Try this:
----------------------------------
struct CS {}; // my version of "CString"
struct A { // my version of your "AbstractDataHolderList"
template<class T> A* foo(); // my "DeleteThisItem"
};

template<class T> A* A::foo() { // definition
T t;
return this;
}

int main() {
A a;
A* pa = &a;
pa = pa->foo<CS>();
}
----------------------------------
It compiles (and links) fine with my copy of VC++ v7.1.

Victor


Thanks for that info... It didn't solve my problem, but it made me
recognize that I was the one with the error... and not the
compiler/linker... (as is always the case... >.<)

I had my template declairation in a header file:

template <class T> ADHL* DelThis();

which was included with all the code that used the class ADHL but the
definition:

template <class T> ADHL* ADHL::DelThis()
{
// Code goes here...
}

was in a separate cpp file... so the compiler never knew about the work the
template was doing until it was too late... Which I'm guessing is a good
type of error to generate (forces people to put templates in headers...
since they are not code in and of themselves).

Thanks for all the help Victor ;) I'd be lost without it 0.o
Jul 22 '05 #5
<de*****@hotmail.com> wrote...
I may have misinterpreted the situation, sorry about that. The .NET (is
that 7.1?) compiler is far more advanced than v6 when the templates are
concerned.

Since you didn't post the complete code, I couldn't verify the error on
any of the compilers available to me here, so I probably fell into
assuming too much. Try this:
----------------------------------
struct CS {}; // my version of "CString"
struct A { // my version of your "AbstractDataHolderList"
template<class T> A* foo(); // my "DeleteThisItem"
};

template<class T> A* A::foo() { // definition
T t;
return this;
}

int main() {
A a;
A* pa = &a;
pa = pa->foo<CS>();
}
----------------------------------
It compiles (and links) fine with my copy of VC++ v7.1.

Victor


Thanks for that info... It didn't solve my problem, but it made me
recognize that I was the one with the error... and not the
compiler/linker... (as is always the case... >.<)

I had my template declairation in a header file:

template <class T> ADHL* DelThis();

which was included with all the code that used the class ADHL but the
definition:

template <class T> ADHL* ADHL::DelThis()
{
// Code goes here...
}

was in a separate cpp file... so the compiler never knew about the work
the template was doing until it was too late... Which I'm guessing is a
good type of error to generate (forces people to put templates in
headers... since they are not code in and of themselves).


You could do this special thing in your separate cpp file: add explicit
instantiations. After the definition of the template member add lines
like these:

template ADHL* ADHL::DelThis<CSting>();
template ADHL* ADHL::DelThis<int>();

and so on, for all types you think are relevant. The compiler will have
to generate all the instantiations mentioned. It usually leads to code
bloat, but it does help hide the implementation, besides if your template
is intended to work only with a limited set of types, it's not such a bad
deal.

Victor
Jul 22 '05 #6
de*****@hotmail.com schrieb:
This code get's a link error (I'm guessing because the template isn't being
instantiated)...

// For using templates to simplify deleting items
template <class T>
// Returns the next ADHL in the list
AbstractDataHolderList*
// Used to delete this object and the item it points to
AbstractDataHolderList::DeleteThisItem(void)
{
// do stuff to update list (since this item is being removed)

delete (typename T*)m_thisItem;
delete this;

return m_nextADHL;


On a side note, the above line looks suspiciously like you're shooting
yourself in the foot there. Assuming m_nextADHL is a member of this,
you must not use it anymore, as this it's no longer valid. To return a
data member's value you need to make a local copy before committing
suicide and then return that copy's value. No more accessing non-static
data members or calling non-static member functions or anything else
that involves the this pointer after self-destruction. Ever.

Regards,
Malte

PS: While such drastic consequences of dereferencing invalid pointers
are unlikely in today's OSs unless you're hacking the kernel, I actually
once killed half of my file system with something like that under DOS...
Jul 22 '05 #7
>
You could do this special thing in your separate cpp file: add explicit
instantiations. After the definition of the template member add lines
like these:

template ADHL* ADHL::DelThis<CSting>();
template ADHL* ADHL::DelThis<int>();

and so on, for all types you think are relevant. The compiler will have
to generate all the instantiations mentioned. It usually leads to code
bloat, but it does help hide the implementation, besides if your template
is intended to work only with a limited set of types, it's not such a bad
deal.

Victor


I like that idea, keeps the code clean enough ;) thanks for the tips ;)
Jul 22 '05 #8

On a side note, the above line looks suspiciously like you're shooting
yourself in the foot there. Assuming m_nextADHL is a member of this, you
must not use it anymore, as this it's no longer valid. To return a data
member's value you need to make a local copy before committing suicide and
then return that copy's value. No more accessing non-static data members
or calling non-static member functions or anything else that involves the
this pointer after self-destruction. Ever.

Regards,
Malte

PS: While such drastic consequences of dereferencing invalid pointers are
unlikely in today's OSs unless you're hacking the kernel, I actually once
killed half of my file system with something like that under DOS...


That was once a error for me, but I fixed that long ago... just showed up in
this code due to lazyness ^.~ What I do is make a local ADHL pointer, then
find out what it should point to (pMyPointer = m_nextItem for example...)
then return the pointer to the next, or previous ADHL... or sometimes NULL.
But thanks for the tip... can never be too safe when it comes to playing
with pointers and delete and such ;)

As a side note... I once blew up a palm pilot screen doing something like
this ;) ok... ok... I only made it go "pop" and only a 4x160 pixel area on
the screen doesn't get drawn... So yah... this stuff is bad to do... thanks
for the reminder ;)
Jul 22 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: 胡岳偉(Yueh-Wei Hu) | last post by:
Hi all, I have 2 questions about template function as friends in template classes. I don't know why, and hope someone could help me. ...
0
by: Yueh-Wei Hu | last post by:
Victor Bazarov <v.Abazarov@comAcast.net> wrote in message news: ============================================================== > > Question 1: > >...
7
by: Drew McCormack | last post by:
I have a C++ template class which contains a static variable whose construction registers the class with a map. Something like this: template <typename T> class M { static Registrar<M>...
3
by: sks | last post by:
Hello all Is the usage of extern keyword valid for telling the compiler to NOT instantiate a template and to link it from an another binary? For example: Suppose module A's binary contains a...
9
by: Christof Warlich | last post by:
Hi, consider this: template<typename Tclass X { public: void doSomething(T t); }; int main(void) { X<intx;
8
by: Imre | last post by:
Hi I'm looking for a way to make sure that whenever a new instance of a class template A is created, then an instance of class template B is also created, with the same template parameters. Of...
7
by: alex221 | last post by:
In need to implement a tree structure in which every node has arbitrary number of children the following code has come into mind: using std::list; template < class Contents class Tree_node{ ...
5
by: emboss | last post by:
If templates worked how I would like them to work, I'd be able to do the following: template <int N> class A { private: int X; public: template <int M> void foo(const A<M>...
8
by: flopbucket | last post by:
Hi, I want to provide a specialization of a class for any type T that is a std::map. template<typename T> class Foo { // ... };
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.