Advertisement

Questions about template classes

Started by March 02, 2000 08:05 AM
10 comments, last by null_pointer 24 years, 8 months ago
I'm making a linked list class, just to see how it works, and for my list's node class, I'd like to do something like this:

template< class TYPE >
class DLL // doubly-linked list
{
protected:
    template< class TYPE >
    class Node
    {
        // other stuff
    }

public:
    // other stuff
};
 
I can define the functions for the Node class inside of the class declaration, but how do I define them outside? Also, can I use inline functions in my template classes, and do they work as usual? Thanks! - null_pointer Edited by - null_pointer on 3/2/00 8:07:28 AM
I''ll tackle the second question first, since it''s easier: Yes. You can definitely do inline template functions, and they work exactly as you''d expect. Most of the STL functions are written as such, which is one of the reasons that generic libraries (like STL) beat the pants off OO-based container libraries, where the virtual functions can''t be inlined.

As for writing the functions outside, you need to be careful. In general, you still need all your functions in the .h file anyway, since delayed instantiation doesn''t really work. (The compiler/linker needs to know exactly which versions of every template need to be generated, and it can only do that if it can see all of the template code when they get instantiated.)

However, you can still write the functions in the .h file, but outside the class. For your case, I think the following should work:

template<class TYPE>
void DLL<TYPE>::Node<TYPE>::someFunc()
{
}

I''m not sure though, I can check later and let you know... Gotta get to school.
-Brian
Advertisement
What was said above is basically correct. Templates are nothing but glorified macros. There is a simple trick you can use to include code that is not inlined in your header (.h) file.

Code a base linked list class using (void *). Use the template to inherit this base class and define methods that redeclare any (void *)s that are necessary.

In a lot of instances, this type of coding is more managable and much easier to debug.
Does that mean that if I have a class like this:

template
class Blah
{
public:
void Function(T Param);
};

I can make the Function function take any param I want??

PS - Sorry about the messed up post... hit the tab key then enter...

--------------------


You are not a real programmer until you end all your sentences with semicolons;
www.trak.to/rdp

Yanroy@usa.com




Edited by - felisandria on 3/2/00 9:50:20 AM
--------------------

You are not a real programmer until you end all your sentences with semicolons; (c) 2000 ROAD Programming
You are unique. Just like everybody else.
"Mechanical engineers design weapons; civil engineers design targets."
"Sensitivity is adjustable, so you can set it to detect elephants and other small creatures." -- Product Description for a vibration sensor

Yanroy@usa.com

Yanroy:

Yes, basically. (As long as there is a <class T> after the template keyword). When you declare an instance of the class, you have to specify what type the instance is going to use. internally, the compiler replaces the T with whatever type you specify. Notice that the type has to be constant... so when you call the "function(T param);" param has to be the same type you used to instantiate the class. for instance using your class definition:

void main() {
int i = 10;
blah<int> B;
B.Function(i);
}


Also, instead of actually typing the function definitions into the .h file, it usually works to add the line

#include "classfile.cpp"

at the end of the .h file. Make sure you use the #ifndef technique on the .h file to prevent it from being compiled more than once.

*oof*

(arrrgh! I hate the less-than symbol stripping!!!)

Edited by - Oofnish on 3/2/00 9:16:42 AM
*oof*
Yeah, I know how to write template classes, but thanks for the replies!

osmanb: For some reason, the example you gave me won't work!? I guess the standard hasn't gotten this far yet? Or maybe it's just a limitation...I really don't know. But thanks for trying!

It gives me "error C2954: template definitions cannot nest" when I try that syntax (outside the class). Here's what the MSDN docs say about that error:


quote:
Compiler Error C2954
template definitions cannot nest

Nested template declarations are not allowed. This error can be caused by improperly matched curly braces ({}).



I could be doing something wrong, though...here's the code I used for the constructor:


template< class TYPE > DLL::Node::Node(TYPE* pData){	m_pPrevious = NULL;	m_pNext = NULL;	m_pData = pData;} 


argh! The board destroyed my angle brackets...well, there's an angle bracket pair '<>' with TYPE in between, for the three template class names, if you can understand my babbling

I tried quite a few variants on that but nothing worked. Has anyone else run into this before? Is this just a problem with the C++ compiler/standard? Or is it my syntax?

Thanks!


- null_pointer



Edited by - null_pointer on 3/2/00 4:31:23 PM

Edited by - null_pointer on 3/2/00 4:33:51 PM
Advertisement
Yeah, I understand. It''s a PITA, but you can use &lt; to get a < and &gt; to get > -- But how did I write that? (:

Anyways, I''ve never actually seen code that does what you want, and I''m not sure if there is any way. (Imagine if the template types were different, what would the declaration look like then?) Ick.

Aha! Nevermind what I just said. Looking at section 14.5.2 of the standard, we see that:

> A member template of a class template that is defined
> outside of its class template definition shall be
> specified with the template-parameters of the class
> template followed by the template-parameters of the member
> template.

The example they provide is based on a template member function of a template class, but it looks like the same style could be used for your code. Try something like:

template <class T> template <class T2>
DLL<T>::Node<T2>::someFunc()
{
}

It''s not exactly the same, but it seems like the best bet, based on that section. I can''t seem to find anything exactly the same as what you have, though. Thinking back, I believe I once saw someone with a similar problem, and the ultimate solution was to make Node a separate class, with only private constructors, and declaring DLL to be a friend. That way, no one else can mess with (or even create) them, but you can still use them freely in you list functions. Good luck!

-Brian
If you want to put the non inline functions into a .cpp file simply include the .cpp file at the end of the .h file. Be sure to use the #ifnde __something_h_ #define __something_h_ #endf. Also do this in the .cpp
osmanb: Unfortunately, it doesn't work that way either

I tried nearly every way I could think of to get it to work outside the class; for now I'll just have to define them inside the class declaration. One other thing I found out about this is that you can't refer to an "embedded" (if I have the term right) template class outside of the template class in which it was declared. So, even if I made Node public the way I have it set up, I could never use a Node outside the class, because the compiler doesn't like the syntax:

DLL&ltint>::Node&ltint>* pIntNode = new DLL&ltint>::Node&ltint>

In that instance, it would keep complaining about casting an int to a Node&ltint>*, int is not defined, it's defined twice, etc. and lots of other things to indicate that its parser's gone slightly mad.

Keeping Node protected is fine for the particular class, but would be very limiting to other classes.

Thanks for trying, and I appreciate the effort; it seems VC++ 6 just doesn't conform with the entire standard. The standard does keep changing, so maybe that support will be included in a future release. I'll try that tip about the private constructors.

Thanks!


- null_pointer


Edited by - null_pointer on 3/3/00 7:07:44 AM
> it seems VC++ 6 just doesn''t conform with the entire
> standard. The standard does keep changing, so maybe that
> support will be included in a future release.

Saying that VC++ 6 "doesn''t conform with the entire standard" is an understatement. I''ve spent many hours experimenting with templates in VC++ 6, and the support for all but the most basic features is horribly broken. You run into non-standard behaviour and internal compiler errors all the time.

I had expected the support to be a little better than this - the C++ standard was finalized quite some time before VC++ 6 was released. C++Builder 4 (and, presumably, Borland C++ 5.5) performs much, much better in this area. Visual Studio 7 should be out pretty soon, but standard compliance is not one of Microsofts strong suits, as we all know by now...

This topic is closed to new replies.

Advertisement