Sign in to follow this  

Can 2 classes share the same template?

This topic is 4595 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

ok, I have 2 classes the are going to make up my custom link list, is it possible for the classes to share the same template. by that i mean if i declare the CustomList class to char for the object, will the ListNodes created by the CustonList Class be char? here is my code:
namespace CList
{
//=================================================================================================================================
// CustomList Class, contains all functions to edit the ListNode Class
//=================================================================================================================================
	template< class cl >
	class CustomList
	{
	public:
		CustomList();
		CustomList( cl el );
		~CustomList();
		void Insert_Front( cl el );
		void Insert_End( cl el );
		bool Is_Empty();
		void Print();

	private:
		CustomList* _first;
		CustomList* _last;
	};

//=================================================================================================================================
// ListNode Class, The containor for the list information
//=================================================================================================================================
	template < class cl >
	class ListNode
	{
	public:
		ListNode( cl el, ListNode* ptr );
		~ListNode();
		cl _info;
		ListNode* _next;

	};
}


Share this post


Link to post
Share on other sites
Firstly the obligatory : you do know about std::list, don't you?

Next, the disclaimer - templates aren't my strong point, and I'll probably get corrected when snk_kid or maulingmonkey wanders past; never-the-less:

Firstly, in your code as posted, there's no relationship between CustomList and ListNode. Therefore, there's no template parameter sharing.

But why would you want ListNode to be a separate class? It's an implementation detail of the list - hence it could be a member class. How's this for starters:


template <typename T> class CustomList
{
private:
class Node
{
public:
Node() {} //Details to be completed
T data_;
Node* next_;
Node* prev_;
};
Node* head_;

public:
// Interface
};



Now the only visible class is the CustomList, which is all we want - why pollute our namespace with the Nodes, which are just an implementation detail?

Next some other comments:

Quote:

void Insert_Front( cl el );


Lists have a common terminology (push, pop, etc.) and you should try and stick to that as much as possible. Otherwise it just confuses other users.

In addition, you are creating a copy of the data to be inserted into the list. It would be better to use:

void Push_Front(const cl& el)

(using your terminology) to avoid creating extraneous copies. Imagine trying to create a CustomList of some big structure - each time you insert an element you have to create a new copy of the big structure - not good.

Quote:

CustomList* _first;


What is CustomList*? With the code snippet you've provided, there is no such thing as a CustomList*. There is a CustomList<cl>* - which is what you'd actually want.

Think that's all my comments on first look through! Hope it gives you some food for thought.

Jim.

Share this post


Link to post
Share on other sites
My advice would be to use std::list.

Failing that you should nest your list node class inside your list class:



template<class T>
class CustomList
{
public:
//public interface

private:
class ListNode
{
public:
ListNode* next;
T value;
};
};


Share this post


Link to post
Share on other sites
Well, the STL is not know for good use when using DLL's and our team does not want to depend on many 3rd party libraries like STL Port so this is the part of my prject i am working on, that is why io am not using teh stl list.

Share this post


Link to post
Share on other sites
Quote:
Well, the STL is not know for good use when using DLL's and our team does not want to depend on many 3rd party libraries like STL Port so this is the part of my prject i am working on, that is why io am not using teh stl list.


What do you mean by that? I've never encountered any problems using the standard library in DLLs. Writing your own containers is error prone - especially if its your first time, as I assume it is seeing as you don't know about this stuff.

Even if you really can't use std::list I'd advise at basing your list interface on it.

Share this post


Link to post
Share on other sites
The STL is now officially named the Standard C++ Library, and should be installed on all systems with C++. If that's too "3rd party" for you, then all libraries are going to be, meaning you're going to be writing assembly for every single OS call to the system. Surely you're not that crazy.

Further, there's no benifit to using your own templatized container over the standard library's containers in terms of DLL boundries.

The main problem you'd face would be if the DLL and EXE were built with different compilers, or different versions of the same compiler. You will have this problem with any class - to allow this one must create a C style interface (read: functions marked "extern C") and not share classes between the two. The easiest method is just to compile both the EXE and DLL with the same compiler and version.

Now, to finally attempt to answer your original question, you've failed to show exactly what you mean, but I'm guessing it's something like this... you want to be able to do:
template < class cl >
CustomList< cl >::CustomList( void )
{
...
... = new ListNode;
...
}
There are a few ways to do this.

1) Specify the template arguments. The assignment line becomes:
... = new ListNode< cl >;
2) Create a typedef. In your class definition, you'd add the line:
typedef ListNode< cl > ListNode;
or similar.

3) Create the node class as a subclass of CustomList:
template < class cl >
class CustomList
{
public:
class ListNode
{
public:
ListNode( void );
...
};
CustomList( void );
...
};

template < class cl >
CustomList< cl >::CustomList( void )
{
... = new ListNode;
}

template < class cl >
CustomList< cl >::ListNode::ListNode( void )
{
}
Out of these options, I suggest #2, this is how the standard libraries do it. While #3 may make sense, it has the annoying tendancy to bloat class definitions into being rather big.

Extremely cut up and reduced excerpt from the standard library:

namespace _GLIBCXX_STD
{
...
struct _List_node_base
{
_List_node_base* _M_next; ///< Self-explanatory
_List_node_base* _M_prev; ///< Self-explanatory
...
};
...
template<typename _Tp>
struct _List_node : public _List_node_base
{
_Tp _M_data; ///< User's data.
};
...
template<typename _Tp>
struct _List_iterator
{
typedef _List_iterator<_Tp> _Self;
typedef _List_node<_Tp> _Node;

typedef ptrdiff_t difference_type;
typedef bidirectional_iterator_tag iterator_category;
typedef _Tp value_type;
typedef _Tp* pointer;
typedef _Tp& reference;

...
};
template<typename _Tp, typename _Alloc = allocator<_Tp> >
class list : protected _List_base<_Tp, _Alloc>
{
// concept requirements
__glibcxx_class_requires(_Tp, _SGIAssignableConcept)

typedef _List_base<_Tp, _Alloc> _Base;

public:
typedef _Tp value_type;
typedef typename _Alloc::pointer pointer;
typedef typename _Alloc::const_pointer const_pointer;
typedef typename _Alloc::reference reference;
typedef typename _Alloc::const_reference const_reference;
typedef _List_iterator<_Tp> iterator;
typedef _List_const_iterator<_Tp> const_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef typename _Base::allocator_type allocator_type;
...
};
...
}


Share this post


Link to post
Share on other sites
I am also doing this for the learning experiance. Um this is my code for my custom list classes:


#ifndef CLIST_H
#define CLIST_H

namespace CList
{
//=================================================================================================================================
// CustomList Class, contains all functions to edit the ListNode Class
//=================================================================================================================================
template< class cl >
class CustomList
{
public:
CustomList();
CustomList( cl el );
~CustomList();
void Insert_Front( cl el );
void Insert_End( cl el );
bool Is_Empty();
void PrintList();

private:
//cl _info;
//CustomList* _next;
CustomList* _first;
CustomList* _last;
};

//=================================================================================================================================
// ListNode Class, The containor for the list information
//=================================================================================================================================
template < class cl >
class ListNode
{
public:
ListNode( cl el, ListNode* ptr );
~ListNode();
cl _info;
ListNode* _next;

};
}

//=================================================================================================================================
// CustomList Methods
//=================================================================================================================================
template< class cl >
CList::CustomList< cl >::CustomList()
{

}
template< class cl >
CList::CustomList< cl >::CustomList( cl el )
{
_first = _last = 0;
//_info = el;
}
template< class cl >
CList::CustomList< cl >::~CustomList()
{

}
template< class cl >
void CList::CustomList< cl >::Insert_Front( cl el )
{
_first = new ListNode< cl >( el, _first );
if ( _last == 0 )
{
_last = _first;
}
}
template< class cl >
void CList::CustomList< cl >::Insert_End( cl el )
{
if ( _last != 0 )
{
_last->_next = new ListNode< cl >( el );
_last = _last->_next;
}
else
{
_last = _first = new ListNode< cl >( el );
}
}
template< class cl >
bool CList::CustomList< cl >::Is_Empty()
{
return _first == 0;
}
template< class cl >
void CList::CustomList< cl >::PrintList()
{
ListNode* tmpptr;
for ( tmpptr = _first; tmpptr != 0; tmpptr = tmpptr->_next )
{
std::cout << _info << std::endl;
}
}

//=================================================================================================================================
// ListNode Methods
//=================================================================================================================================
template < class cl >
CList::ListNode< cl >::ListNode( cl el, ListNode* ptr = 0 )
{
_info = el;
next = ptr;
}
template < class cl >
CList::ListNode< cl >::~ListNode()
{

}
#endif



Now my thinking was that when i had a line of code like this:

_first = new ListNode< cl >( el, _first );

that the cl would be replaced with whatever i declared the CustomList object and then the ListNode Object would be the same.

here it part of my main.cpp code:

CList::CustomList< char > *charlist = new CList::CustomList< char >();

charlist->Insert_Front( 'r' );



and this is my error i am getting:

------ Build started: Project: CustomList, Configuration: Debug Win32 ------

Compiling...
main.cpp
c:\Documents and Settings\ryan\My Documents\Visual Studio Projects\CustomList\clist.h(65) : error C2664: 'CList::ListNode<ln>::ListNode(ln,CList::ListNode<ln> *)' : cannot convert parameter 2 from 'CList::CustomList<cl> *' to 'CList::ListNode<ln> *'
with
[
ln=char
]
and
[
cl=char
]
and
[
ln=char
]
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\xmemory(136) : while compiling class-template member function 'void CList::CustomList<cl>::Insert_Front(cl)'
with
[
cl=char
]
c:\Documents and Settings\ryan\My Documents\Visual Studio Projects\CustomList\main.cpp(7) : see reference to class template instantiation 'CList::CustomList<cl>' being compiled
with
[
cl=char
]

Build log was saved at "file://c:\Documents and Settings\ryan\My Documents\Visual Studio Projects\CustomList\Debug\BuildLog.htm"
CustomList - 1 error(s), 0 warning(s)


---------------------- Done ----------------------

Build: 0 succeeded, 1 failed, 0 skipped

Share this post


Link to post
Share on other sites
Quote:
Original post by 3dmodelerguy
and this is my error i am getting:
*** Source Snippet Removed ***


Comon, that's an easy error :-). Here's the important part:

"cannot convert parameter 2 from 'CList::CustomList<cl> *' to 'CList::ListNode<ln> *'"

I'm guessing line 65 is this one:

_first = new ListNode< cl >( el, _first );

Now, how is _first defined? Like so, in your class definition:

CustomList* _first;

Since the two classes are not directly related (neither inherits from the other) this is obviously an error :-).

Share this post


Link to post
Share on other sites
Quote:
Original post by 3dmodelerguy
ok, how do i fix that? I tried adding this line but the just adds 1 more error ontop on the one i already have

class CustomList : public ListNode


the definition of ListNode would have to come before CustomList.

Note that having CustomList inherit from ListNode is extremely bad mojo. What happens when you want to have a list with zero objects in it? If CustomList is itself the first node, you can't have a list with less than 1 object.

What you probably want is to change _first and _last to:

ListNode * _first;
ListNode * _last;

After all, the first and last nodes you're pointing at arn't entire lists in and of themselves, are they? They're parts of a list.

Share this post


Link to post
Share on other sites

This topic is 4595 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this