Container Class that holds two classes

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
JFT
Posts: 11
Joined: Mon Feb 02, 2009 5:32 pm

Container Class that holds two classes

Post by JFT »

Hi,

I am currently trying to write a container class that holds 2 classes:
I am trying to use the code of the irrlist.h http://pastebin.com/pbAAZu33 and modify it.

my class looks like that right now...:

Code: Select all

#ifndef MOVECONTAINER_H
#define MOVECONTAINER_H

#include <irrlicht.h>
#include <list>


using namespace irr;
using namespace core;


template<class T1,class T2>
class movecontainer
{
private:

	//! List element node with pointer to previous and next element in the list.
	struct SKListMove
	{
		SKListMove(const T1& e1,const T2& e2) : Next(0), Prev(0), Element1(e), Element2(e2) {}

		SKListMove* Next;
		SKListMove* Prev;
		T1 Element1;
		T2 Element2;
	};

public:
	class ConstIterator;

	//! List iterator.
	class Iterator
	{
	public:
		Iterator() : Current(0) {}

		Iterator& operator ++()    { Current = Current->Next; return *this; }
		Iterator& operator --()    { Current = Current->Prev; return *this; }
		Iterator  operator ++(s32) { Iterator tmp = *this; Current = Current->Next; return tmp; }
		Iterator  operator --(s32) { Iterator tmp = *this; Current = Current->Prev; return tmp; }

		Iterator& operator +=(s32 num)
		{
			if(num > 0)
			{
				while (num-- && this->Current != 0) ++(*this);
			}
			else
			{
				while(num++ && this->Current != 0) --(*this);
			}
			return *this;
		}

		Iterator  operator + (s32 num) const { Iterator tmp = *this; return tmp += num; }
		Iterator& operator -=(s32 num) const { return (*this)+=(-num); }
		Iterator  operator - (s32 num) const { return (*this)+ (-num); }

		bool operator ==(const Iterator&      other) const { return Current == other.Current; }
		bool operator !=(const Iterator&      other) const { return Current != other.Current; }
		bool operator ==(const ConstIterator& other) const { return Current == other.Current; }
		bool operator !=(const ConstIterator& other) const { return Current != other.Current; }

		#if defined (_MSC_VER) && (_MSC_VER < 1300)
			#pragma warning(disable:4284) // infix notation problem when using iterator operator ->
		#endif

		T & operator * () { return Current->Element; }
		T * operator ->() { return &Current->Element; }

	private:
		explicit Iterator(SKListMove* begin) : Current(begin) {}

		SKListMove* Current;

		friend class movecontainer<T1,T2>;
		friend class ConstIterator;
	};

	//! List iterator for const access.
	class ConstIterator
	{
	public:

		ConstIterator() : Current(0) {}
		ConstIterator(const Iterator& iter) : Current(iter.Current)  {}

		ConstIterator& operator ++()    { Current = Current->Next; return *this; }
		ConstIterator& operator --()    { Current = Current->Prev; return *this; }
		ConstIterator  operator ++(s32) { ConstIterator tmp = *this; Current = Current->Next; return tmp; }
		ConstIterator  operator --(s32) { ConstIterator tmp = *this; Current = Current->Prev; return tmp; }

		ConstIterator& operator +=(s32 num)
		{
			if(num > 0)
			{
				while(num-- && this->Current != 0) ++(*this);
			}
			else
			{
				while(num++ && this->Current != 0) --(*this);
			}
			return *this;
		}

		ConstIterator  operator + (s32 num) const { ConstIterator tmp = *this; return tmp += num; }
		ConstIterator& operator -=(s32 num) const { return (*this)+=(-num); }
		ConstIterator  operator - (s32 num) const { return (*this)+ (-num); }

		bool operator ==(const ConstIterator& other) const { return Current == other.Current; }
		bool operator !=(const ConstIterator& other) const { return Current != other.Current; }
		bool operator ==(const Iterator&      other) const { return Current == other.Current; }
		bool operator !=(const Iterator&      other) const { return Current != other.Current; }

		const T & operator * () { return Current->Element; } //GUCKEN!!!!!!!!!!!!!!
		const T * operator ->() { return &Current->Element; }

		ConstIterator & operator =(const Iterator & iterator) { Current = iterator.Current; return *this; }

	private:
		explicit ConstIterator(SKListMove* begin) : Current(begin) {}

		SKListMove* Current;

		friend class Iterator;
		friend class movecontainer<T1,T2>;
	};

	//! Default constructor for empty list.
	list()
		: First(0), Last(0), Size(0) {}


	//! Copy constructor.
	list(const movecontainer<T1,T2>& other) : First(0), Last(0), Size(0)
	{
		*this = other;
	}


	//! Destructor
	~movecontainer()
	{
		clear();
	}


	//! Assignment operator
	void operator=(const movecontainer<T1,T2>& other)
	{
		if(&other == this)
		{
			return;
		}

		clear();

		SKListMove* node = other.First;
		while(node)
		{
			push_back(node->Element);
			node = node->Next;
		}
	}


	//! Returns amount of elements in list.
	/** \return Amount of elements in the list. */
	u32 size() const
	{
		return Size;
	}
	u32 getSize() const
	{
		return Size;
	}


	//! Clears the list, deletes all elements in the list.
	/** All existing iterators of this list will be invalid. */
	void clear()
	{
		while(First)
		{
			SKListMove * next = First->Next;
			allocator.destruct(First);
			allocator.deallocate(First);
			First = next;
		}

		//First = 0; handled by loop
		Last = 0;
		Size = 0;
	}


	//! Checks for empty list.
	/** \return True if the list is empty and false if not. */
	bool empty() const
	{
		return (First == 0);
	}


	//! Adds an element at the end of the list.
	/** \param element Element to add to the list. */
	void push_back(const T1& element1,const T2& element2)
	{
		SKListMove* node = allocator.allocate(1);
		allocator.construct(node, element1,element2);

		++Size;

		if (First == 0)
			First = node;

		node->Prev = Last;

		if (Last != 0)
			Last->Next = node;

		Last = node;
	}


	//! Adds an element at the begin of the list.
	/** \param element: Element to add to the list. */
	void push_front(const T1& element1,const T2& element2)
	{
		SKListMove* node = allocator.allocate(1);
		allocator.construct(node, element1,element2);

		++Size;

		if (First == 0)
		{
			Last = node;
			First = node;
		}
		else
		{
			node->Next = First;
			First->Prev = node;
			First = node;
		}
	}


	//! Gets first node.
	/** \return A list iterator pointing to the beginning of the list. */
	Iterator begin()
	{
		return Iterator(First);
	}


	//! Gets first node.
	/** \return A const list iterator pointing to the beginning of the list. */
	ConstIterator begin() const
	{
		return ConstIterator(First);
	}


	//! Gets end node.
	/** \return List iterator pointing to null. */
	Iterator end()
	{
		return Iterator(0);
	}


	//! Gets end node.
	/** \return Const list iterator pointing to null. */
	ConstIterator end() const
	{
		return ConstIterator(0);
	}


	//! Gets last element.
	/** \return List iterator pointing to the last element of the list. */
	Iterator getLast()
	{
		return Iterator(Last);
	}


	//! Gets last element.
	/** \return Const list iterator pointing to the last element of the list. */
	ConstIterator getLast() const
	{
		return ConstIterator(Last);
	}


	//! Inserts an element after an element.
	/** \param it Iterator pointing to element after which the new element
	should be inserted.
	\param element The new element to be inserted into the list.
	*/
	void insert_after(const Iterator& it, const T1& element1,const T2& element2)
	{
		SKListMove* node = allocator.allocate(1);
		allocator.construct(node,element1,element2);

		node->Next = it.Current->Next;

		if (it.Current->Next)
			it.Current->Next->Prev = node;

		node->Prev = it.Current;
		it.Current->Next = node;
		++Size;

		if (it.Current == Last)
			Last = node;
	}


	//! Inserts an element before an element.
	/** \param it Iterator pointing to element before which the new element
	should be inserted.
	\param element The new element to be inserted into the list.
	*/
	void insert_before(const Iterator& it, const T1& element1,const T2& element2)
	{
		SKListNode* node = allocator.allocate(1);
		allocator.construct(node, element1, element2);

		node->Prev = it.Current->Prev;

		if (it.Current->Prev)
			it.Current->Prev->Next = node;

		node->Next = it.Current;
		it.Current->Prev = node;
		++Size;

		if (it.Current == First)
			First = node;
	}


	//! Erases an element.
	/** \param it Iterator pointing to the element which shall be erased.
	\return Iterator pointing to next element. */
	Iterator erase(Iterator& it)
	{
		// suggest changing this to a const Iterator& and
		// working around line: it.Current = 0 (possibly with a mutable, or just let it be garbage?)

		Iterator returnIterator(it);
		++returnIterator;

		if(it.Current == First)
		{
			First = it.Current->Next;
		}
		else
		{
			it.Current->Prev->Next = it.Current->Next;
		}

		if(it.Current == Last)
		{
			Last = it.Current->Prev;
		}
		else
		{
			it.Current->Next->Prev = it.Current->Prev;
		}

		allocator.destruct(it.Current);
		allocator.deallocate(it.Current);
		it.Current = 0;
		--Size;

		return returnIterator;
	}

	//! Swap the content of this list container with the content of another list
	/** Afterwards this object will contain the content of the other object and the other
	object will contain the content of this object. Iterators will afterwards be valid for
	the swapped object.
	\param other Swap content with this object	*/
	void swap(movecontainer<T1,T2>& other)
	{
		core::swap(First, other.First);
		core::swap(Last, other.Last);
		core::swap(Size, other.Size);
		core::swap(allocator, other.allocator);	// memory is still released by the same allocator used for allocation
	}


private:

	SKListMove* First;
	SKListMove* Last;
	u32 Size;
	irrAllocator<SKListMove> allocator;
};

#endif // MOVECONTAINER_H
Is it even possible to write a container class that holds 2 classes. Maybe there already someone who wrote one before.

I would appreciate any help on that!

Thanks for your help,

JFT[/url]
serengeor
Posts: 1712
Joined: Tue Jan 13, 2009 7:34 pm
Location: Lithuania

Post by serengeor »

why not just use std::map?
Working on game: Marrbles (Currently stopped).
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Post by sudi »

how about?

Code: Select all

#include <irrList.h>

template<class A, class B>
class TwoObjects
{
public:
    TwoObjects(A a, B b)
    {
        First = a;
        Second = b;
    }
    TwoObjects(void) : First(A()) , Second(B())
    {
    }
    TwoObjects(const TwoObjects& other)
    {
        *this = other;
    }
    TwoObjects& operator=(const TwoObjects& other)
    {
        First = other.First;
        Second = other.Second;
        return *this;
    }
    bool operator==(const TwoObjects& other)
    {
        return (First == other.First && Second == other.Second);
    }
    A First;
    B Second;
};

int main(int argc, char* args[])
{
    irr::core::list<TwoObjects<int, float> > two;
    two.push_back(TwoObjects<int, float>(3, 5.4f));

    irr::core::list<TwoObjects<int, float> >::Iterator it = two.begin();

    (*it).First = 2;
    (*it).Second = 987.43f;

    printf("Obj: %i %f\n", (*it).First, (*it).Second);

    *it = TwoObjects<int, float>(3, 5.4f);

    printf("Obj: %i %f\n", (*it).First, (*it).Second);
   
    return 0;
}
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
JFT
Posts: 11
Joined: Mon Feb 02, 2009 5:32 pm

Post by JFT »

thanks for the quick answers! Now,i have to decide if a use Sudis code or a map instead.
Thanks to both of you.
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Post by sudi »

well a map is something totally different. A map maps one value to another.
You can access the second value with the first for example.

Code: Select all

irr::core::map<irr::core::stringc, irr::u32> myMap;
myMap["Age"] = 32;
myMap["Phone"] = 345678;
myMap["Count"] = 2;
a list on the other hand is just for storing data with quick insert and remove.[/code]
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
Post Reply