See what's going on with flipcode!




This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

 

  Array Templates
  Submitted by



Hi!
These are my array templates.
It may not work with vc++, I haven't tested yet, and there are several typedefs etc missing which are in other headers. I can't describe all the functions etc in detail, but give a general overview of its functionality:

Array is a simple array for data, it doesn't construct/deconstruct objects if you use it with objects: template<typename T,uint size=DYNAMIC> class Array; T should be clear, size is either the size of the array(->static array) or DYNAMIC It allocates new data if you increase its size, but it doesn't deallocate it if you decrease it, so it prevents reallocating all the time.

Objectarray is quite complicated to understand, but not to use it. Objectarray<Class> gives you a default object array which allocates/deallocates and constructs/deconstructs the objects.

Objectarray<Class,CALL,uint,YES> creates an objectarray of Class'es which are constructed if you increase its size, but called Class::Destruct if you decrease it. When you increase its size again Class::Construct(uint) is called for each object. The objects have static position so you can have pointers to them. I'm going to describe the 4 template parameters in the following lines:

template <class T,Enum initmode=NORMAL,typename inittype=NoInitobject,Boolean staticposition=NO> class Objectarray
T: the type of the objects
initmode:   -  NONE:   objects aren't constructed/destructed
            -  NORMAL: objects are constructed/destructed with their constructors/destructors
            -  CALL:   objects are constructed through their constructors at first creation, and destructed
                       when you do Objectarray::Free or when the Objectarray is deconstructed.
                       runtime construction/destruction is done through T::Construct/T::Destruct.
                       the reason for that feature is that T could also contain dynamic arrays which
                       are always deallocated in the destructor of T with NORMAL. in T::Destruct you can set their size
                       to zero but not deallocate them and reuse the memory when T is reconstructed.

inittype: the type of the object which is passed to T::T (NORMAL or CALL) or/and T::Construct (CALL) NoInitobject if you don't need that. That's only a dummy because c++ doesn't support that functionality, class NoInitobject is empty.

staticposition: - NO: Objectarray allocates all objects as one array. So when you do Objectarray::SetNumber or something similar it has to reallocate that array, so the position in memory of the objects may change. So you can't take external pointers to the object, you always have to access them through Objectarray::operator[] (or something similar again) - YES: you can take pointers to the objects, they have static position in memory. each of them are allocated through new T.


The arrays are probably not very usable for you as they are, but may help you implementing your own. Such templates really help in development, I don't have one dynamic array in my code which doesn't use these templates, no more coding the same again and again.

Also I have almost no crashes in debug mode(assert()'s) since I use them (at least noones which aren't related to bugs in the array templates :)

cu,
Sengir

Currently browsing [arrobject.zip] (4,875 bytes) - [object.h] - (9,863 bytes)

#ifndef S3D_ARRAY_OBJECT_H
#define S3D_ARRAY_OBJECT_H

#include <s3d/array.h>

namespace Sengir3D{

class NoInitobject{}; template<typename inittype,Enum initmode> class Objectarrayhelper{}; template<typename inittype> class Objectarrayhelper<inittype,NONE>{ public: template<typename T> inline void ConstructObject(T &) const{} template<typename T> inline void DestructObject(T &) const{} inline inittype GetInitobject() const{ return NoInitobject(); } inline Objectarrayhelper(const inittype &){} }; template<typename inittype> class Objectarrayhelper<inittype,NORMAL>{ private: inittype initobject; public: template<typename T> inline void ConstructObject(T &object) const{ new (&object) T(initobject); } template<typename T> inline void DestructObject(T &object) const{ object.~T(); } inline inittype GetInitobject() const{ return initobject; } inline Objectarrayhelper(const inittype &newinitobject) : initobject(newinitobject){} }; template<> class Objectarrayhelper<NoInitobject,NORMAL>{ public: template<typename T> inline void ConstructObject(T &object) const{ new (&object) T; } template<typename T> inline void DestructObject(T &object) const{ object.~T(); } inline NoInitobject GetInitobject() const{ return NoInitobject(); } inline Objectarrayhelper(const NoInitobject &){} }; template<typename inittype> class Objectarrayhelper<inittype,CALL>{ private: inittype initobject; public: template<typename T> inline void ConstructObject(T &object) const{ object.Construct(initobject); } template<typename T> inline void DestructObject(T &object) const{ object.Destruct(); } inline inittype GetInitobject() const{ return initobject; } inline Objectarrayhelper(const inittype &newinitobject) : initobject(newinitobject){} }; template<> class Objectarrayhelper<NoInitobject,CALL>{ public: template<typename T> inline void ConstructObject(T &object) const{ object.Construct(); } template<typename T> inline void DestructObject(T &object) const{ object.Destruct(); } inline NoInitobject GetInitobject() const{ return NoInitobject(); } inline Objectarrayhelper(const NoInitobject &){} };

template<class T,Enum initmode,typename inittype,Boolean staticposition> class Objectarraybase{}; template<class T,Enum initmode,typename inittype> class Objectarraybase<T,initmode,inittype,NO> : protected Array<T>,protected Objectarrayhelper<inittype,initmode>{ protected: void Reallocate(uint newallocated){ element=(T *)realloc(element,sizeof(T)*newallocated); assert(element); if(initmode!=NORMAL) for(uint c=allocated;c<newallocated;c++) new (element+c) T; allocated=newallocated; } public: inline void SetNumber(uint newnumber){ uint c; if(newnumber > number){ if(newnumber > allocated) Reallocate(newnumber); for(c=number;c<newnumber;c++) ConstructObject(element[c]); }else{ for(c=newnumber;c<number;c++) DestructObject(element[c]); } number=newnumber; } protected: void Free(){ if(initmode!=NORMAL) for(uint c=0;c<allocated;c++) element[c].~T(); allocated=0; if(element){ free(element); element=NULL; } } public: inline const T &operator[](uint i) const{ assert(i < number); return element[i]; } inline T &operator[](uint i){ assert(i < number); return element[i]; } inline void Exchange(Reference ref1,Reference ref2){ Array<T>::Exchange(ref1,ref2); } inline void RemoveElement(uint i){ Exchange(i,number-1); SetNumber(number-1); } void Remove(const T &oldelement){ for(int c=number-1;c>=0;c--){ if(element[c]==oldelement){ RemoveElement(c); return; } } throw ElementNotFound(); } inline Objectarraybase(const inittype &newinitobject=NoInitobject()) : Objectarrayhelper<inittype,initmode>(newinitobject){} }; template<class T,Enum initmode,typename inittype> class Objectarraybase<T,initmode,inittype,YES> : protected Array<T *>,protected Objectarrayhelper<inittype,initmode>{ protected: void Reallocate(uint newallocated){ uint c; element=(T **)realloc(element,sizeof(T *)*newallocated); assert(element); if(initmode!=NORMAL) for(c=allocated;c<newallocated;c++) element[c]=new T; else for(c=allocated;c<newallocated;c++) element[c]=(T *)malloc(sizeof(T)); allocated=newallocated; } public: inline void SetNumber(uint newnumber){ uint c; if(newnumber > number){ if(newnumber > allocated) Reallocate(newnumber); for(c=number;c<newnumber;c++) ConstructObject(*(element[c])); }else{ for(c=newnumber;c<number;c++) DestructObject(*(element[c])); } number=newnumber; } protected: void Free(){ uint c; if(initmode!=NORMAL) for(c=0;c<allocated;c++) delete element[c]; else for(c=0;c<allocated;c++) free(element[c]); allocated=0; if(element){ free(element); element=NULL; } } public: inline const T &operator[](uint i) const{ assert(i < number); return *(element[i]); } inline T &operator[](uint i){ assert(i < number); return *(element[i]); } inline Objectarraybase(const inittype &newinitobject=NoInitobject()) : Objectarrayhelper<inittype,initmode>(newinitobject){} };

template<class T,Enum initmode,typename inittype,Boolean staticposition> class Objectarray : public Objectarraybase<T,initmode,inittype,staticposition>{ public: inline uint GetNumber() const{ return number; } inline void SetMinNumber(uint minnumber){ if(minnumber > number) SetNumber(minnumber); } inline void Clear(){ for(uint c=0;c<number;c++) DestructObject(operator[](c)); number=0; } void Free(){ Clear(); Objectarraybase<T,initmode,inittype,staticposition>::Free(); } inline void Construct(){ number=0; } inline void Destruct(){ Clear(); } inline void Add(const T &newelement){ SetNumber(number+1); operator[](number-1)=newelement; } template<Enum initmode2,typename inittype2,Boolean staticposition2> void Add(const Objectarray<T,initmode2,inittype2,staticposition2> &addarray){ for(uint c=0;c<addarray.GetNumber();c++) Add(addarray[c]); } inline void operator++(int){ SetNumber(number+1); } inline void operator--(int){ assert(number>0); SetNumber(number-1); } inline void operator+=(uint add){ SetNumber(number+add); } inline void operator-=(uint sub){ assert(number >= sub); SetNumber(number-sub); } inline Reference GetReference(const T &element,Enum parameter=REQUIRED) const{ for(int c=number-1;c>=0;c--) if(operator[](c)==element) return c; if(parameter==REQUIRED) throw ElementNotFound(); else return INVALID; } inline Boolean Contains(const T &element) const{ for(int c=number-1;c>=0;c--) if(operator[](c)==element) return YES; return NO; } Objectarray<T,initmode,inittype,staticposition> &operator=(const Objectarray<T,initmode,inittype,staticposition> &newarray){ if(&newarray!=this){ SetNumber(newarray.GetNumber()); for(uint c=0;c<number;c++) operator[](c)=newarray[c]; } return *this; } template<Enum initmode2,typename inittype2,Boolean staticposition2> Objectarray<T,initmode,inittype,staticposition> &operator=(const Objectarray<T,initmode2,inittype2,staticposition2> &newarray){ if(&newarray!=this){ SetNumber(newarray.GetNumber()); for(uint c=0;c<number;c++) operator[](c)=newarray[c]; } } explicit inline Objectarray(const inittype &newinitobject=NoInitobject()) : Objectarraybase<T,initmode,inittype,staticposition>(newinitobject) {} Objectarray(const Objectarray<T,initmode,inittype,staticposition> &newarray) : Objectarraybase<T,initmode,inittype,staticposition>(newarray.GetInitobject()){ operator=(newarray); } template<Enum initmode2,typename inittype2,Boolean staticposition2> Objectarray(const Objectarray<T,initmode2,inittype2,staticposition2> &newarray) : Objectarraybase<T,initmode,inittype,staticposition>(newarray.GetInitobject()){ operator=(newarray); } template<Enum initmode2,typename inittype2,Boolean staticposition2> Objectarray(const Objectarray<T,initmode2,inittype2,staticposition2> &newarray,const inittype &newinitobject) : Objectarraybase<T,initmode,inittype,staticposition>(newinitobject){ operator=(newarray); } inline ~Objectarray(){ Free(); } };

} #endif


Currently browsing [arrobject.zip] (4,875 bytes) - [array.h] - (9,625 bytes)

#ifndef S3D_ARRAY_H
#define S3D_ARRAY_H

#include <s3d/error.h>

namespace Sengir3D{

template<typename T,uint size> class Array{ protected: T element[size]; public: inline uint GetNumber() const{ return size; } inline void Construct(){} inline void Destruct(){} inline void Set(uint nr,const T newelement){ assert(nr < size); element[nr]=newelement; } inline Reference GetReference(const T e,Enum parameter=REQUIRED) const{ for(uint c=0;c<size;c++) if(element[c]==e) return c; if(parameter==REQUIRED) throw ElementNotFound(); else return INVALID; } template<uint size2> inline Array<T,size> &operator=(const Array<T,size2> &newarray){ if(this != &newarray){ assert(newarray.GetNumber() == size); memcpy(element,newarray.element,size*sizeof(T)); } } inline Array<T,size> &operator=(const Array<T,size> &newarray){ if(this != &newarray) memcpy(element,newarray.element,size*sizeof(T)); return *this; } template<uint size2> inline bool operator==(const Array<T,size2> &array2) const{ if(array2.GetNumber() != size) return false; for(uint c=0;c<size;c++){ if(element[c]!=array2[c]) return false; } return true; } template<uint size2> inline bool operator!=(const Array<T,size2> &array2) const{ return !(operator==(array2)); } inline void Exchange(Reference ref1,Reference ref2){ assert(ref1 < size); assert(ref2 < size); byte temp[sizeof(T)]; memcpy(temp,element+ref1,sizeof(T)); memcpy(element+ref1,element+ref2,sizeof(T)); memcpy(element+ref2,temp,sizeof(T)); } inline Boolean Contains(const T &e) const{ for(uint c=0;c<size;c++) if(element[c]==e) return YES; return NO; } inline Array(){} inline const T *Get() const{ return element; } inline const T &Get(uint nr) const{ assert(nr < size); return element[nr]; } inline const T &operator[](uint i) const{ assert(i<size); return element[i]; } inline T &operator[](uint i){ assert(i<size); return element[i]; } inline operator const T *() const{ return element; } inline operator T *(){ return element; } inline operator const void *() const{ return element; } inline operator void *(){ return element; } template<uint size2> inline Array(const Array<T,size2> &newarray){ operator=(newarray); } inline Array(const Array<T,size> &newarray){ operator=(newarray); } };

template<typename T> class Array<T,DYNAMIC>{ protected: uint number,allocated; T *element; public: inline uint GetNumber() const { return number; } inline void Clear(){ number=0; } inline void Construct(){} inline void Destruct(){ Clear(); } inline void Free(){ Clear(); allocated=0; if(element){ free(element); element=NULL; } } private: void Reallocate(uint newnumber){ element=(T *)realloc(element,sizeof(T)*newnumber); assert(element); allocated=newnumber; } inline void Resize(uint newnumber){ if(newnumber>allocated) Reallocate(newnumber); number=newnumber; } public: inline void Add(const T newelement){ Resize(number+1); element[number-1]=newelement; } template<uint size> inline void Add(const Array<T,size> &newarray){ for(uint c=0;c<newarray.GetNumber();c++) Add(newarray[c]); } inline void Set(uint nr,const T newelement){ assert(nr<number); element[nr]=newelement; } inline void RemoveElement(uint nr){ element[nr]=element[number-1]; number--; } inline void Remove(const T oldelement){ for(int c=number-1;c>=0;c--){ if(element[c]==oldelement){ RemoveElement(c); return; } } throw ElementNotFound(); } inline Reference GetReference(const T e,Enum parameter=REQUIRED) const { for(int c=number-1;c>=0;c--) if(element[c]==e) return c; if(parameter==REQUIRED) throw ElementNotFound(); else return INVALID; } template<uint size> inline Array<T,DYNAMIC> &operator= (const Array<T,size> &newarray){ if(&newarray!=this){ Resize(newarray.GetNumber()); memcpy(element,newarray.element,number*sizeof(T)); } return *this; } inline Array<T,DYNAMIC> &operator= (const Array<T,DYNAMIC> &newarray){ if(this != &newarray){ Resize(newarray.GetNumber()); memcpy(element,newarray.element,number*sizeof(T)); } return *this; } template<uint size> inline bool operator ==(const Array<T,size> &array2) const{ if(number!=array2.number) return false; for(uint c=0;c<number;c++){ if(element[c]!=array2[c]) return false; } return true; } template<uint size> inline bool operator !=(const Array<T,size> &array2) const{ return !(operator==(array2)); } inline void SetNumber(uint newnumber){ Resize(newnumber); } inline void SetMinNumber(uint minnumber){ if(number<minnumber){ Resize(minnumber); } } inline void operator++ (int){ Resize(number+1); } inline void operator+=(uint add){ Resize(number+add); } inline void operator-- (int){ assert(number>0); number--; } inline void operator-=(uint sub){ assert(number>=sub); number-=sub; } void Insert(uint nr,const T newelement){ if(nr>=number){ SetNumber(nr+1); element[nr]=newelement; }else{ SetNumber(number+1); for(int c=number-2;c>=(int)nr;c--) element[c+1]=element[c]; element[nr]=newelement; } } void Insert(const T element1,const T element2,const T newelement){ uint v1,v2; for(v1=0;v1<number;v1++){ if(v1!=number-1) v2=v1+1; else v2=0; if(((element[v1]==element1)&&(element[v2]==element2))||((element[v1]==element2)&&(element[v2]==element1))){ return Insert(v1+1,newelement); } } throw ElementNotFound(); } inline void Exchange(Reference ref1,Reference ref2){ assert(ref1 < number); assert(ref2 < number); byte temp[sizeof(T)]; memcpy(temp,element+ref1,sizeof(T)); memcpy(element+ref1,element+ref2,sizeof(T)); memcpy(element+ref2,temp,sizeof(T)); } inline Boolean Contains(const T &e) const{ for(int c=number;c>=0;c--) if(element[c]==e) return YES; return NO; } inline Array() : number(0),allocated(0),element(NULL){} inline void Initialize(){ number=allocated=0; element=NULL; } inline const T *Get() const{ return element; } inline const T &Get(uint nr) const{ assert(nr<number); return element[nr]; } inline const T &operator[](uint i) const{ assert(i<number); return element[i]; } inline T &operator[](uint i){ assert(i<number); return element[i]; } inline operator const T *() const{ return element; } inline operator T *() { return element; } inline operator const void *() const{ return element; } inline operator void *(){ return element; } template<uint size> inline Array(const Array<T,size> &newarray) : number(0),allocated(0),element(NULL){ operator=(newarray); } inline Array(const Array<T,DYNAMIC> &newarray) : number(0),allocated(0),element(NULL){ operator=(newarray); } inline explicit Array(uint newnumber) : number(0),allocated(0),element(NULL){ SetNumber(newnumber); } inline Array(uint newnumber,T *newelement) : number(newnumber),allocated(newnumber){ if(number>0){ assert(newelement); element=malloc(sizeof(T)*number); assert(element); memcpy(element,newelement,sizeof(T)*number); }else element=NULL; } inline ~Array(){ Free(); } };



} #endif //S3D_ARRAY_H

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

 

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.