Jump to content

Templated Linked List


Josh
 Share

Recommended Posts

I wrote my own LinkedList class that is a lot simpler than messing around with STL iterators. It uses the Leadwerks3D Object class for the link values. I'd like to be able to create lists for entities, integers, strings, or whatever else. Does anyone know how to use templates to make this declarable like stl lists are?:

LinkedList<Entity*> list;

linkedlist.rar

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

But why... can't see the genius in doing that! But its your engine, not mine :)

 

However, think it will be something like this...

Have not tested, just written.

 

 

 

Link.h

#pragma once
namespace Leadwerks3D
{
template<typename T>
class LinkedList;

template <typename T>
class Link
{
friend class LinkedList<T>;
T* value;
Link* prev;
Link* next;
LinkedList<T>* list;
public:
Link()
: value(nullptr),
prev(nullptr),
next(nullptr),
list(nullptr)
{}
~Link()
{
if (list->firstlink==this) list->firstlink=next;
if (list->lastlink==this) list->lastlink=prev;
if (prev) prev->next=next;
if (next) next->prev=prev;
value=nullptr;
}


Link* NextLink() const
{
return next;
}
Link* PrevLink() const
{
return prev;
}
T* GetValue() const
{
return value;
}
};
}

 

LinkedList.h

#include "Link.h"
namespace Leadwerks3D
{
template <typename>
class Link;
template <typename T>
class LinkedList
{
friend class Link<T>;

Link<T>* firstlink;
Link<T>* lastlink;
public:
LinkedList()
: firstlink(nullptr),
lastlink(nullptr)
{}
~LinkedList()
{
Link<T>* link = firstlink;
Link<T>* nextlink;
while (link!=nullptr)
{
nextlink=link->next;
link->next=nullptr;
link->prev=nullptr;
delete link;
}
}
Link<T>* GetFirstLink() const
{
return firstlink;
}
Link<T>* GetLastLink() const
{
return lastlink;
}

Link<T>* AddLast(T* o)
{
Link<T>* link = new Link<T>;
link->value = o ;
link->prev = lastlink ;
link->list = this;
if (lastlink)
{
lastlink->next=link;
}
else
{
firstlink=link;
}
lastlink = link;
return link;
}
Link<T>* AddFirst(T* o)
{
Link<T>* link = new Link<T>;
link->value= o;
link->next = firstlink;
link->list = this;
if (firstlink)
{
firstlink->prev=link;
}
else
{
lastlink=link;
}
firstlink = link;
return link;
}

static LinkedList<T>* Create()
{
return new LinkedList<T>;
}
};
}

 

Use like this

 

#include "LinkedList.h"
using namespace Leadwerks3D;

class ABC
{
};

int main(int argc, char* argv[])
{
LinkedList<ABC> list;
list.AddFirst(new ABC() );
list.AddLast(new ABC() );

return 0;
}

AV MX Linux

Link to comment
Share on other sites

Using STL is quite standard and would be a positive thing. There are many advantages with STL iterators, as the ability to have several iterators operation on the same list at once, it also have a bunch of nice features that I would miss. So my recommendation is STL, but Josh has the internal overview of the code and may have some reason to use non-standard lists.

AV MX Linux

Link to comment
Share on other sites

If this stuff is ever to be exposed to the user then I would say use iterators because the C++ programmers will be familiar with it and there are a bunch of algorithms already available to work with those containers. Why write your own?

  • Upvote 2
Link to comment
Share on other sites

STL lists suck because they return iterators as objects, not pointers. With pointers, you know if a value is NULL it is no good:

 

Link* link = list.AddLast(o);
delete link;
link=NULL;

 

With STL iterators, you have no idea whether an iterator is valid or not:

std::list<Object*>::iterator it = list.begin();
list.erase(it);
//it still hangs around, can't be changed to NULL

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

You do it wrong.

 

With STL iterators, you have no idea whether an iterator is valid or not:

std::list<Object*>::iterator it = list.begin();
list.erase(it);
//it still hangs around, can't be changed to NULL

 

Do it like this: (MSDN: std::list.erase http://msdn.microsoft.com/en-us/library/1fef72t6%28v=vs.80%29.aspx )

std::list<Object*> list;
list.push_back(new Object());
std::list<Object*>::iterator it = list.begin();
it = list.erase(it);
if (it == list.end()) // similiar to == null
{
   std::cout << "no more entry" << std::endl;
}

 

ps. Im sorry to refer so much to the MSDN but its the best source for (v)c++ documentation.

Link to comment
Share on other sites

You do it wrong.

 

 

 

Do it like this: (MSDN: std::list.erase http://msdn.microsof...6(v=vs.80).aspx )

std::list<Object*> list;
list.push_back(new Object());
std::list<Object*>::iterator it = list.begin();
it = list.erase(it);
if (it == list.end()) // similiar to == null
{
std::cout << "no more entry" << std::endl;
}

 

ps. Im sorry to refer so much to the MSDN but its the best source for (v)c++ documentation.

That's somewhat better, but I still don't like this because you always have to have the list and the iterator. Why can't the iterator just remember which list it belongs to?

 

Besides the to be or not to be discussion. Did my example solve your problem Josh?

Haven't got to try it yet, but I have the solution here so I can go back to it later.

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

That's somewhat better, but I still don't like this because you always have to have the list and the iterator. Why can't the iterator just remember which list it belongs to?

 

Whats the problem ? Since the iterator is created on stack, you can just create new instance when you need it.

  • Upvote 1
Link to comment
Share on other sites

I think STL::list is faster than a self-made simple list with pointers. I noticed that when I made one in Fortran, but I haven't speed tested yet how much speed difference there is in C++.

  • Upvote 1

Ryzen 9 RX 6800M ■ 16GB XF8 Windows 11 ■
Ultra ■ LE 2.53DWS 5.6  Reaper ■ C/C++ C# ■ Fortran 2008 ■ Story ■
■ Homepage: https://canardia.com ■

Link to comment
Share on other sites

I think STL::list is faster than a self-made simple list with pointers. I noticed that when I made one in Fortran, but I haven't speed tested yet how much speed difference there is in C++.

 

There's been a speed test between STL classes and Doom 3's implementation of the respective classes, STL's classes showed significantly faster speed.

 

I would suggest to use STL for primitive containers such as lists or vectors, which are probably the fastest implementation out there.

Blog & Portfolio

 

Current project: moon.chase.star

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...