📄 exparr.hpp
字号:
T *ta; INT cur_size; INT max_size;};template <class T, class INT=int>class EaIter {public: EaIter( const ExpArr<T,INT> &ea ) : m_pea(&ea), m_ix(0) { } void Init( INT ix=0 ) { m_ix=ix; } T Get() { if( m_ix<0 || m_ix>=m_pea->Size() ) EA_THROW_RV( "EaIter::Get, Index out of range", m_pea->GetNullElem() ); return m_pea->Elem(m_ix); }T operator () () { return Get(); } int Index( ) { return m_ix; } void operator ++ () { m_ix++; } void operator ++ (int) { m_ix++; } // postfix void operator -- () { m_ix--; } void operator -- (int) { m_ix--; } // postfix bool AtEnd() { return m_ix>=m_pea->Size(); }protected: const ExpArr<T> *m_pea; INT m_ix;};// ----- ExpArrP -----// The pointer versiontemplate<class T, class INT=int >class ExpArrP : public ExpArr<T,INT> {public: ExpArrP( const T *pt, INT n ) : ExpArr<T,INT>(pt,n) { } ExpArrP( const ExpArrP<T,INT> &ea ) : ExpArr<T,INT>(ea) { } ExpArrP( const ExpArrP<T,INT> &ea, bool is_move ) : ExpArr<T,INT>(ea,is_move) { } ExpArrP( ) : ExpArr<T,INT>() { } //~ExpArrP(); // # ExpArrP specific void DeleteAll( ) { for( int ix=0; ix<this->cur_size; ix++ ) delete this->ta[ix]; this->Empty(); } // # ExpArrP specific, for efficiency T ElemSafe( INT ix ) const { if( ix<0 || ix>=this->cur_size ) return NULL; else return this->ta[ix]; } // Use operator==: T t; U u; t==u template<class U> int FindIndexOf( const U &u, int ix=0, int dir=1 ) { for( ; ix>=0 && ix<this->cur_size; ix+=dir ) if( this->ta[ix] && (*(this->ta[ix]))==u ) return ix; return -1; } // Use operator==: T t; U u; u==t template<class U> int FindIndexOfR( const U &u, int ix=0, int dir=0 ) { for( ; ix>=0 && ix<this->cur_size; ix+=dir ) if( this->ta[ix] && u==(*(this->ta[ix])) ) return ix; return -1; } // Use operator==: T t; U u; t==u template<class U> T Find( const U &u ) { INT ix = FindIndexOf(u); return ElemSafe(ix); } // Use operator==: T t; U u; u==t template<class U> T FindR( const U &u ) { INT ix = FindIndexOfR(u); return ElemSafe(ix); }};template <class T, class INT=int>class EapIter : public EaIter<T,INT> {public: EapIter( const ExpArrP<T,INT> &ea ) : EaIter<T,INT>(ea) { } T Get() { if( this->m_ix<0 || this->m_ix >= this->m_pea->Size() ) m_t = NULL; else m_t = this->m_pea->Elem(this->m_ix); return m_t; } T operator () () { return Get(); } T m_t;};/*template <class T,class INT=int>class EapIter {public: EapIter( const ExpArrP<T,INT> &ea ) : m_pea(&ea), m_ix(0) {} //{ EA_ASSERT(m_pea); } void Init( int ix=0 ) { m_ix=ix; } T Get() { return m_pea->ElemSafe(m_ix); } T operator () () { return m_pea->ElemSafe(m_ix); } int Index( ) { return m_ix; } void operator ++ () { m_ix++; } void operator ++ (int) { m_ix++; } // postfix void operator -- () { m_ix--; } void operator -- (int) { m_ix--; } // postfix bool AtEnd() { return m_ix>=m_pea->Size(); } protected: const ExpArrP<T,INT> *m_pea; int m_ix;};*/#include "ExpArr.hpp"// We would want placement new below. However, together with debug new operators// this becomes tricky. Instead choose to init each element with values from// GetNullElem. (we could use placement new in release version, but then we get// slightly different meanings to the operations)./*#ifdef new // Define way of replacing placement new#else #include <new>#endif*/// This version holds objects with constructors and/or destructors being applied to them// When an object goes out of the array scope, its destructor is applied.// When an object comes into the scope, its constructor is applied.// Otherwise, we interpret things at 'object scope', not at raw memory level.template <class T, class INT=int>class ExpArrObj : public ExpArr<T,INT> {public: ExpArrObj( const T *pt, INT n ) : ExpArr<T,INT>() { Push(pt,n); } ExpArrObj( const ExpArrObj<T> &ea ) : ExpArr<T,INT>() { Push(ea); } // Special constructor to move contents from other ExpArrr, breaking const, // but that has to be due to C++ restriction in this case. ExpArrObj( const ExpArr<T> &ea, bool is_move ) : ExpArr<T,INT>(ea,is_move) { } ExpArrObj( ) : ExpArr<T,INT>() { } ~ExpArrObj( ) { DestroyAll(); } void Empty() { DestroyAll(); } ExpArrObj& DestroyAll( ) { // Reduce size first, then delete elems int sz = this->cur_size; this->cur_size = 0; for( int ix=0; ix<sz; ix++ ) this->ta[ix].~T(); return *this; } void MinCurrentSize( INT size ) { this->MinTotalSize(size); for( int ix=this->cur_size; ix<size; ix++ ) memcpy( this->ta+ix, &this->GetNullElem(), sizeof(T) ); //new ((void*)(this->ta+ix)) T(); this->cur_size = size; } // It is probably good for ExpArrObj to return a reference by default (?) T& Elem( INT ix ) const { if( ix<0 || ix>=this->cur_size ) EA_THROW_RV("ExpArrObj::Elem - Index out of range",this->GetNullElem()); return this->ta[ix]; } ExpArrObj& Push( const T& elem ) { this->MinFreeElem(1); // Placement new to run constructor memcpy( this->ta+this->cur_size, &this->GetNullElem(), sizeof(T) ); //new ((void*)(this->ta+this->cur_size))T(); this->ta[this->cur_size++] = elem; return *this; } // Push an elemnt but don't set it to anything (meaning run constructor on it) ExpArrObj& Push( ) { this->MinFreeElem(1); // Placement new to run constructor memcpy( this->ta+this->cur_size++, &this->GetNullElem(), sizeof(T) ); //new ((void*)(this->ta+this->cur_size++))T(); return *this; } ExpArrObj& PushVol( T& elem ) { // Allows for operator = to modify elem this->MinFreeElem(1); // Placement new to run constructor memcpy( this->ta+this->cur_size, &this->GetNullElem(), sizeof(T) ); //new ((void*)(this->ta+this->cur_size))T(); this->ta[this->cur_size++] = elem; // Here! return *this; } ExpArrObj& PushElem( T elem ) { // Copy element here (needed?) this->MinFreeElem(1); // Placement new to run constructor memcpy( this->ta+this->cur_size, &this->GetNullElem(), sizeof(T) ); //new ((void*)(this->ta+this->cur_size))T(); this->ta[this->cur_size++] = elem; return *this; } void Pop( ) { if( !this->cur_size ) EA_THROW_RV( "ExpArrObj::Pop, Empty stack", (ExpArr<T,INT>::GetNullElem()) ); this->ta[this->cur_size].~T(); // No return element } INT IndexOf( const T& elem, INT ix=0, INT dir=1 ) const { for(; ix>=0 && ix<this->cur_size; ix+=dir) if(this->ta[ix]==elem) return ix; return (INT)-1; } bool Has( const T& elem ) const { return IndexOf(elem)!=-1; } void RemoveIndexUnordered( INT ix ) { this->RangeCheck(ix); this->ta[ix].~T(); ExpArr<T,INT>::RemoveIndex(ix); } void RemoveIndexOrdered( INT ix ) { this->RangeCheck(ix); this->ta[ix].~T(); ExpArr<T,INT>::RemoveIndexOrdered(ix); } bool Remove( const T &elem ) { INT ix = this->IndexOf(elem); if( ix==(INT)-1 ) return false; RemoveIndex(ix); return true; } bool RemoveUnordered( const T &elem ) { INT ix = this->IndexOf(elem); if( ix==(INT)-1 ) return false; RemoveIndexUnordered(ix); return true; } bool RemoveOrdered( const T &elem ) { INT ix = this->IndexOf(elem); if( ix==-1 ) return false; RemoveIndexOrdered(ix); return true; } ExpArrObj& InsertOrdered( const T &elem, INT ix ) { this->MakeSpaceAt( ix ); memcpy( this->ta+ix, &this->GetNullElem(), sizeof(T) ); //new ((void*)(this->ta+ix)) T(); // If we have custom allocator, this might not have happened this->ta[ix] = elem; return *this; } int Replace( const T& find, const T& repl ) { int n_found = 0; for(INT ix=0; ix<this->cur_size; ix++) if( this->ta[this->ix]==find ) { this->ta[this->ix]=repl; n_found++; } return n_found; } ExpArrObj& Push( const ExpArrObj<T,INT>& other ) { // At top of stack return Insert( other.ExpArr<T,INT>::ta, other.ExpArr<T,INT>::cur_size, this->cur_size ); } ExpArrObj& Push( const T *elems, INT number ) { // At top of stack if( !number ) return *this; return Insert( elems, number, this->cur_size ); } ExpArrObj& Insert( const T *elems, INT number, INT at_ix=0 ) { // At arbitrary position if( !number ) return *this; if( !elems ) EA_THROW_RV( "ExpArrObj::Insert, NULL pointer received", *this ); if( at_ix<0 ) at_ix+=this->cur_size; if( number<0 ) EA_THROW_RV( "ExpArrObj::Insert, Negative number", *this ); if( at_ix<0 || at_ix>this->cur_size ) EA_THROW_RV( "ExpArrObj::Push, Index out of reange", *this ); //MinFreeElem(number); MakeSpaceAt( at_ix, number ); for( int ix=0; ix<number; ix++ ) { memcpy( this->ta+at_ix+ix, &this->GetNullElem(), sizeof(T) ); //new ((void*)(this->ta+at_ix+ix)) T(); this->ta[at_ix+ix] = elems[ix]; } return *this; } ExpArrObj& Remove( INT number, INT at_ix ) { // At arbitrary position if( number<0 || at_ix<0 || at_ix+number>this->cur_size ) EA_THROW_RV( "ExpArr::Remove, Invalid number and/or index", *this ); INT to_ix = at_ix+number; // Destructors on elements to be removed for( INT ix=at_ix; ix<to_ix; ix++ ) this->ta[this->ix].~T(); ExpArr<T,INT>::Remove(number,at_ix); return *this; } ExpArrObj& operator = ( const ExpArrObj<T,INT>& other ) { // Same code as base case, but Push calls local func this->Empty(); Push( other.ta, other.cur_size ); return *this; } bool operator == ( const ExpArrObj<T,INT>& other ) const { if( this->cur_size!=other.cur_size ) return false; for( INT ix=0;ix<this->cur_size;ix++ ) if ( !(this->ta[ix]==other.ta[ix]) ) return false; return true; }};// ExpArrPOwn is the owner of its elements and will delete all elems in destructortemplate<class T, class INT=int >class ExpArrPOwn : public ExpArrP<T,INT> {public: // Forwarding ctors ExpArrPOwn( const T *pt, INT n ) : ExpArrP<T,INT>(pt,n) { } ExpArrPOwn( const ExpArr<T,INT> &ea ) : ExpArrP<T,INT>(ea) { } ExpArrPOwn( const ExpArr<T,INT> &ea, bool is_move ) : ExpArrP<T,INT>(ea,is_move) { } ExpArrPOwn( ) : ExpArrP<T,INT>() { } ~ExpArrPOwn(){ this->DeleteAll(); }};// Type registration, if typeof.h included before us#ifdef TYPEOF_H #undef TYPE_REG_FILE #define TYPE_REG_FILE 100 TYPE_REG_T2(ArrBase) TYPE_REG_T2(ExpArr) // We need to redo the InnerType stuff TYPE_REG_T2(ExpArrObj) TYPE_REG_T2(ExpArrP) TYPE_REG_T2(ExpArrPOwn) template<class T, class INT> struct IterTypes<ExpArrObj<T,INT> > { // integer default index typedef int ix_type; // For ExpArrObj, use reference by default typedef T& e_type; static T& GetEInit(){ return ExpArrObj<T,INT>::GetNullElem(); } };#endif/*// An ExpArr that has a custome allocatortemplate <class T, class INT=int, AllocFunc AF=&NewArrAlloc<T>, FreeFunc FF=&DelArrFree<T> >class ExpArrAlloc {public:};*/#endif // EXPARR_HPP
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -