The ATL3 array template (CSimpleArray) is buggy and leaky -- don't use it (note: ATL7 finally repairs the bugs in CSimpleArray, and also offers a newer template, CAtlArray).
The CSimpleVector<> template requires T to have a meaningful default ctor, copy ctor,
and assignment-operator. The Find method requires T to have a meaningful
operator==.
ATLX::CSimpleVector<CMyClass> vec1; ATLX::CSimpleVector<float,float> vec2;
In the above examples, vec1 will pass arguments by reference, but vec2
will pass arguments as float (not float&).
#pragma once
namespace ATLX
{
template<class T, class A=T&>
class CSimpleVector
{
// Implementaion
private:
struct CInPlaceNewWrapper
{
T t;
CInPlaceNewWrapper(const T& _t) : t(_t)
{ }
void* operator new(size_t n, void* p)
{ return p; }
};
T* m_pT;
int m_nSize,m_nAllocSize;
// Initializers
public:
CSimpleVector()
{
m_pT = 0;
m_nSize = m_nAllocSize = 0;
}
CSimpleVector(const CSimpleVector<T,A>& src)
{
m_pT = 0;
m_nSize = m_nAllocSize = 0;
(*this) = src;
}
CSimpleVector& operator=(const CSimpleVector<T,A>& src)
{
RemoveAll();
Append(src);
return (*this);
}
~CSimpleVector()
{
RemoveAll();
free(m_pT);
}
// Accessors
public:
int GetSize() const
{ return m_nSize; }
bool IsEmpty() const
{ return (m_nSize==0); }
T& operator[](int i) const
{ ATLASSERT(i >= 0 && i < m_nSize);
return (m_pT[i]); }
void CopyTo(T* pt) const
{ ::CopyMemory(pt,m_pT,m_nSize*sizeof(T)); }
int Find(A a) const
{
for(int i = 0; i < m_nSize; i++)
if (m_pT[i] == a) // requires meaningful T::operator==
return i;
return -1;
}
// Operations
public:
void Reserve(int i)
{
ATLASSERT(i >= 0);
if (i > 0)
{
// Expand the allocation
if (i < m_nSize) i = m_nSize;
m_pT = (T*)realloc(m_pT,i*sizeof(T));
m_nAllocSize = i;
}
else // i == 0
{
// Trim the fat, if any
if (m_nSize == 0)
{ free(m_pT); m_pT = 0; }
else if (m_nSize < m_nAllocSize)
{ m_pT = (T*)realloc(m_pT,m_nSize*sizeof(T)); }
m_nAllocSize = m_nSize;
}
}
void Push(A a)
{
if (m_nSize == m_nAllocSize)
Reserve((m_nAllocSize==0)?(4):(m_nAllocSize*2)); // first alloc == 4*sizeof(T)
m_nSize++;
new(m_pT+m_nSize-1) CInPlaceNewWrapper(a);
}
T Pop()
{
ATLASSERT(m_nSize != 0);
T t = m_pT[m_nSize-1];
m_pT[m_nSize-1].~T();
m_nSize--;
return t;
}
void Append(const CSimpleVector<T,A>& src)
{
for(int i = 0; i < src.GetSize(); i++)
Push(src[i]);
}
void RemoveAll()
{
for(int i = 0; i < m_nSize; i++)
m_pT[i].~T();
m_nSize = 0;
}
void Swap(int x, int y)
{
ATLASSERT(x >= 0 && x < m_nSize);
ATLASSERT(y >= 0 && y < m_nSize);
T* pt = (T*)malloc(sizeof(T));
::CopyMemory(pt,&m_pT[x],sizeof(T));
::CopyMemory(&m_pT[x],&m_pT[y],sizeof(T));
::CopyMemory(&m_pT[y],pt,sizeof(T));
free(pt);
}
void Sort()
{
// Non-destructive swap-sort (as deterined by T::operator<)
bool bDone = false;
while (!bDone)
{
bDone = true;
for (int i=0; i < (m_nSize-1); i++)
{
if (m_pT[i+1] < m_pT[i])
{
Swap(i,i+1);
bDone = false;
}
}
}
}
};
} // namespace
