Introduction
I believe anyone who programmed for a while would have encountered the need for lists, sorted or unsorted, for different types of objects. Anyway, I did, and I wanted an easy way to have lists without the need of writing basically the same code for each type. Although there are the vector and map templates, I found their use a bit too demanding for me, and I had set my mind to write my own code, which so far served me very well.
Template's Definition
The template class does the simple act of taking care of memory allocation, while the derived sorted one adds logarithmic sorting functionality as well. The list template has three members. m_list
which is a pointer to the list of objects, size
and max
. The size
variable is the number of active places in the list, and the max
variable is the actual size of allocated places in the list. Sorted lists have another public member bMultiple
which allows them to have multiple objects in case the comparison method indicates they are equal.
Definition:
template <class T, class F=T, class S=Int16>
class AIList {
T
stands for the list's type, F
for the type of object passed for the Add
method for creating new T
objects, and S
is the type for the size
and max
variables. In the sorted list for pointers, the object has to have an int Compare(F&)
method, and for non pointers an overloaded int
operator -(F&)
.
Methods
Here are the methods of the base class AIList
:
void Attach (AIList <T, F, S>& p)
{ RemoveAll(true); size = p.GetSize();
max = p.GetMax(); m_list = p.Detach(); }
void Attach (T* p, S n)
{ if (m_list) delete [] m_list; size = max = n; m_list = p; }
void SetMinSize (S n) { if (max < n) GrowBy (n - max); }
void GrowBy (S n);
void AddActive (S n)
{ if (size + n > max) { GrowBy (size + n - max); size = max; }
else size +=n; }
void Add (F& obj, S nPos = -1);
void Add (AIList <T, F, S>& obj, S nPos);
AIList <T, F, S>& operator += (AIList <T, F, S>& p);
AIList <T, F, S>& operator = (AIList <T, F, S>& p)
{ RemoveAll(); return *this += p; }
T* Detach () { T* tmp = m_list; size = max = 0; m_list = 0; return tmp; }
void RemoveAt (S pos, T* obj = 0);
void RemoveAll (bool bReset = true)
{ if (max && bReset)
{ delete []m_list; m_list = 0; max = 0; }
size = 0; }
void Remove (T& p, T* obj = 0) { RemoveAt (Find (p), obj); }
void RemoveLast (T* obj = 0) { RemoveAt (size-1, obj); }
void FreeList (bool bReset = true)
{ for (S i=size ; i-- ; )
{ if (m_list[i]) delete m_list[i]; }
RemoveAll(bReset); }
const T& GetLast() const { ASSERT (size); return m_list[size-1]; }
const T& operator [] (S pos) const
{ ASSERT (!pos || pos < size); return m_list[pos]; }
T& GetLast() { ASSERT (size); return m_list[size-1]; }
T& operator [] (S pos) { ASSERT (!pos || pos < size); return m_list[pos]; }
S Find (T& obj, S nStart = 0) const { ... }
bool operator == (AIList <T, F, S>& p) const;
void FitToSize();
Example
class Word {
char* m_desc;
public:
Word() { m_desc = 0; }
Word(char* p) { m_desc = strdup(p); }
~Word() { if (m_desc) delete m_desc; }
int Compare(char* p) { return stricmp (m_desc, p); }
const char* GetDesc() { return m_desc; }
};
void main() {
AISortedList<Word, char*> words;
char* pp = "foo";
words.Add (pp);
...
words.FreeList();
}
Remarks
Three things that are worth noting are:
- The algorithm for memory allocation in the
Add
and RemoveAt
methods, which might be changed to a different one: template<class T, class F, class S>
void AIList<T, F, S>::Add (F& obj, S nPos) {
...
if (size == max) {
==> max += max/2 + 1;
tmp = new T [max];
for (i=0 ; i<nPos ; i++) tmp[i] = m_list[i];
} else tmp = m_list;
...
}
template<class T, class F, class S>
void AIList<T, F, S>::RemoveAt (S pos, T* obj) {
...
==> if (size < max / 2) {
==> tmp = new T [size];
for (i=0 ; i<pos ; i++) tmp[i] = m_list[i];
max = size;
} else tmp = m_list;
...
}
- The
int
type for the comparison results in the FindHelper
method for the sorted lists. The problem with the int
type is that in float
or double
types the comparison is of course not valid if the difference is less than 1. template <class T, class F, class S>
bool AISortedList2<T, F, S>::FindHelper (F& p, S& pos) const {
int r; ...
r = m_list[pos] - p; ...
}
- There are probably some places for improvement.
Conclusion
I hope you find good use for this code. Any remarks or suggestions are more than welcome.