Replace object array macros with template class too
Put the code implementing object arrays, i.e. arrays owning pointers to the objects, into wxBaseObjectArray<> instead of _WX_DECLARE_OBJARRAY macro. Also simplify WX_DEFINE_OBJARRAY() by leaving only the definitions of functions creating and destroying the objects in it (they have to be there and not in the template itself to allow using template with incomplete classes).
This commit is contained in:
@@ -9,7 +9,7 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* Purpose: implements methods of "template" class declared in *
|
* Purpose: implements helper functions used by the template class used by *
|
||||||
* DECLARE_OBJARRAY macro and which couldn't be implemented inline *
|
* DECLARE_OBJARRAY macro and which couldn't be implemented inline *
|
||||||
* (because they need the full definition of type T in scope) *
|
* (because they need the full definition of type T in scope) *
|
||||||
* *
|
* *
|
||||||
@@ -19,101 +19,15 @@
|
|||||||
* 4) WX_DEFINE_OBJARRAY *
|
* 4) WX_DEFINE_OBJARRAY *
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
// needed to resolve the conflict between global T and macro parameter T
|
#undef WX_DEFINE_OBJARRAY
|
||||||
|
#define WX_DEFINE_OBJARRAY(name) \
|
||||||
#define _WX_ERROR_REMOVE2(x) wxT("bad index in ") wxT(#x) wxT("::RemoveAt()")
|
name::value_type* \
|
||||||
|
wxObjectArrayTraitsFor##name::Clone(const name::value_type& item) \
|
||||||
// macro implements remaining (not inline) methods of template list
|
|
||||||
// (it's private to this file)
|
|
||||||
#undef _DEFINE_OBJARRAY
|
|
||||||
#define _DEFINE_OBJARRAY(T, name) \
|
|
||||||
name::~name() \
|
|
||||||
{ \
|
{ \
|
||||||
Empty(); \
|
return new name::value_type(item); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
void name::DoCopy(const name& src) \
|
void wxObjectArrayTraitsFor##name::Free(name::value_type* p) \
|
||||||
{ \
|
{ \
|
||||||
for ( size_t ui = 0; ui < src.size(); ui++ ) \
|
delete p; \
|
||||||
Add(src[ui]); \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
name& name::operator=(const name& src) \
|
|
||||||
{ \
|
|
||||||
Empty(); \
|
|
||||||
DoCopy(src); \
|
|
||||||
\
|
|
||||||
return *this; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
name::name(const name& src) : wxArrayPtrVoid() \
|
|
||||||
{ \
|
|
||||||
DoCopy(src); \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
void name::DoEmpty() \
|
|
||||||
{ \
|
|
||||||
for ( size_t ui = 0; ui < size(); ui++ ) \
|
|
||||||
delete (T*)base_array::operator[](ui); \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
void name::RemoveAt(size_t uiIndex, size_t nRemove) \
|
|
||||||
{ \
|
|
||||||
wxCHECK_RET( uiIndex < size(), _WX_ERROR_REMOVE2(name) ); \
|
|
||||||
\
|
|
||||||
for (size_t i = 0; i < nRemove; i++ ) \
|
|
||||||
delete (T*)base_array::operator[](uiIndex + i); \
|
|
||||||
\
|
|
||||||
base_array::erase(begin() + uiIndex, begin() + uiIndex + nRemove); \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
void name::Add(const T& item, size_t nInsert) \
|
|
||||||
{ \
|
|
||||||
if (nInsert == 0) \
|
|
||||||
return; \
|
|
||||||
T* pItem = new T(item); \
|
|
||||||
size_t nOldSize = size(); \
|
|
||||||
if ( pItem != NULL ) \
|
|
||||||
base_array::insert(end(), nInsert, pItem); \
|
|
||||||
for (size_t i = 1; i < nInsert; i++) \
|
|
||||||
base_array::operator[](nOldSize + i) = new T(item); \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
void name::Insert(const T& item, size_t uiIndex, size_t nInsert) \
|
|
||||||
{ \
|
|
||||||
if (nInsert == 0) \
|
|
||||||
return; \
|
|
||||||
T* pItem = new T(item); \
|
|
||||||
if ( pItem != NULL ) \
|
|
||||||
base_array::insert(begin() + uiIndex, nInsert, pItem); \
|
|
||||||
for (size_t i = 1; i < nInsert; i++) \
|
|
||||||
base_array::operator[](uiIndex + i) = new T(item); \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
int name::Index(const T& item, bool bFromEnd) const \
|
|
||||||
{ \
|
|
||||||
if ( bFromEnd ) { \
|
|
||||||
if ( size() > 0 ) { \
|
|
||||||
size_t ui = size() - 1; \
|
|
||||||
do { \
|
|
||||||
if ( (T*)base_array::operator[](ui) == &item ) \
|
|
||||||
return static_cast<int>(ui); \
|
|
||||||
ui--; \
|
|
||||||
} \
|
|
||||||
while ( ui != 0 ); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
else { \
|
|
||||||
for( size_t ui = 0; ui < size(); ui++ ) { \
|
|
||||||
if( (T*)base_array::operator[](ui) == &item ) \
|
|
||||||
return static_cast<int>(ui); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
return wxNOT_FOUND; \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// redefine the macro so that now it will generate the class implementation
|
|
||||||
// old value would provoke a compile-time error if this file is not included
|
|
||||||
#undef WX_DEFINE_OBJARRAY
|
|
||||||
#define WX_DEFINE_OBJARRAY(name) _DEFINE_OBJARRAY(_wxObjArray##name, name)
|
|
||||||
|
@@ -237,7 +237,7 @@ public:
|
|||||||
|
|
||||||
size_t IndexForInsert(T item) const
|
size_t IndexForInsert(T item) const
|
||||||
{
|
{
|
||||||
return this->IndexForInsert(item, (CMPFUNC)m_fnCompare);
|
return this->wxBaseArray<T>::IndexForInsert(item, (CMPFUNC)m_fnCompare);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddAt(T item, size_t index)
|
void AddAt(T item, size_t index)
|
||||||
@@ -264,63 +264,173 @@ private:
|
|||||||
// _WX_DECLARE_OBJARRAY: an array for pointers to type T with owning semantics
|
// _WX_DECLARE_OBJARRAY: an array for pointers to type T with owning semantics
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
#define _WX_DECLARE_OBJARRAY(T, name, base, classexp) \
|
// This class must be able to be declared with incomplete types, so it doesn't
|
||||||
typedef int (CMPFUNC_CONV *CMPFUNC##T)(T **pItem1, T **pItem2); \
|
// actually use type T in its definition, and relies on a helper template
|
||||||
classexp name : protected base \
|
// parameter, which is declared by WX_DECLARE_OBJARRAY() and defined by
|
||||||
{ \
|
// WX_DEFINE_OBJARRAY(), for providing a way to create and destroy objects of
|
||||||
typedef int (CMPFUNC_CONV *CMPFUNC##base)(void **pItem1, void **pItem2); \
|
// type T
|
||||||
typedef base base_array; \
|
template <typename T, typename Traits>
|
||||||
public: \
|
class wxBaseObjectArray : private wxBaseArray<T*>
|
||||||
name() { } \
|
{
|
||||||
name(const name& src); \
|
typedef wxBaseArray<T*> base;
|
||||||
name& operator=(const name& src); \
|
|
||||||
\
|
public:
|
||||||
~name(); \
|
typedef T value_type;
|
||||||
\
|
|
||||||
void Alloc(size_t count) { base::reserve(count); } \
|
typedef int (wxCMPFUNC_CONV *CMPFUNC)(T **pItem1, T **pItem2);
|
||||||
void reserve(size_t count) { base::reserve(count); } \
|
|
||||||
size_t GetCount() const { return base_array::size(); } \
|
wxBaseObjectArray()
|
||||||
size_t size() const { return base_array::size(); } \
|
{
|
||||||
bool IsEmpty() const { return base_array::empty(); } \
|
}
|
||||||
bool empty() const { return base_array::empty(); } \
|
|
||||||
size_t Count() const { return base_array::size(); } \
|
wxBaseObjectArray(const wxBaseObjectArray& src) : base()
|
||||||
void Shrink() { base::Shrink(); } \
|
{
|
||||||
\
|
DoCopy(src);
|
||||||
T& operator[](size_t uiIndex) const \
|
}
|
||||||
{ return *(T*)base::operator[](uiIndex); } \
|
|
||||||
T& Item(size_t uiIndex) const \
|
wxBaseObjectArray& operator=(const wxBaseObjectArray& src)
|
||||||
{ return *(T*)base::operator[](uiIndex); } \
|
{
|
||||||
T& Last() const \
|
Empty();
|
||||||
{ return *(T*)(base::operator[](size() - 1)); } \
|
DoCopy(src);
|
||||||
\
|
|
||||||
int Index(const T& lItem, bool bFromEnd = false) const; \
|
return *this;
|
||||||
\
|
}
|
||||||
void Add(const T& lItem, size_t nInsert = 1); \
|
|
||||||
void Add(const T* pItem) \
|
~wxBaseObjectArray()
|
||||||
{ base::push_back((T*)pItem); } \
|
{
|
||||||
void push_back(const T* pItem) \
|
Empty();
|
||||||
{ base::push_back((T*)pItem); } \
|
}
|
||||||
void push_back(const T& lItem) \
|
|
||||||
{ Add(lItem); } \
|
void Alloc(size_t count) { base::reserve(count); }
|
||||||
\
|
void reserve(size_t count) { base::reserve(count); }
|
||||||
void Insert(const T& lItem, size_t uiIndex, size_t nInsert = 1); \
|
size_t GetCount() const { return base::size(); }
|
||||||
void Insert(const T* pItem, size_t uiIndex) \
|
size_t size() const { return base::size(); }
|
||||||
{ base::insert(begin() + uiIndex, (T*)pItem); } \
|
bool IsEmpty() const { return base::empty(); }
|
||||||
\
|
bool empty() const { return base::empty(); }
|
||||||
void Empty() { DoEmpty(); base::clear(); } \
|
size_t Count() const { return base::size(); }
|
||||||
void Clear() { DoEmpty(); base::clear(); } \
|
void Shrink() { base::Shrink(); }
|
||||||
\
|
|
||||||
T* Detach(size_t uiIndex) \
|
T& operator[](size_t uiIndex) const
|
||||||
{ T* p = (T*)base::operator[](uiIndex); \
|
{
|
||||||
base::erase(begin() + uiIndex); return p; } \
|
return *base::operator[](uiIndex);
|
||||||
void RemoveAt(size_t uiIndex, size_t nRemove = 1); \
|
}
|
||||||
\
|
|
||||||
void Sort(CMPFUNC##T fCmp) { base::Sort((CMPFUNC##base)fCmp); } \
|
T& Item(size_t uiIndex) const
|
||||||
\
|
{
|
||||||
private: \
|
return *base::operator[](uiIndex);
|
||||||
void DoEmpty(); \
|
}
|
||||||
void DoCopy(const name& src); \
|
|
||||||
}
|
T& Last() const
|
||||||
|
{
|
||||||
|
return *(base::operator[](size() - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
int Index(const T& item, bool bFromEnd = false) const
|
||||||
|
{
|
||||||
|
if ( bFromEnd )
|
||||||
|
{
|
||||||
|
if ( size() > 0 )
|
||||||
|
{
|
||||||
|
size_t ui = size() - 1;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if ( base::operator[](ui) == &item )
|
||||||
|
return static_cast<int>(ui);
|
||||||
|
ui--;
|
||||||
|
}
|
||||||
|
while ( ui != 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for ( size_t ui = 0; ui < size(); ++ui )
|
||||||
|
{
|
||||||
|
if( base::operator[](ui) == &item )
|
||||||
|
return static_cast<int>(ui);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return wxNOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Add(const T& item, size_t nInsert = 1)
|
||||||
|
{
|
||||||
|
if ( nInsert == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
T* const pItem = Traits::Clone(item);
|
||||||
|
|
||||||
|
const size_t nOldSize = size();
|
||||||
|
if ( pItem != NULL )
|
||||||
|
base::insert(this->end(), nInsert, pItem);
|
||||||
|
|
||||||
|
for ( size_t i = 1; i < nInsert; i++ )
|
||||||
|
base::operator[](nOldSize + i) = Traits::Clone(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Add(const T* pItem)
|
||||||
|
{
|
||||||
|
base::push_back(const_cast<T*>(pItem));
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_back(const T* pItem) { Add(pItem); }
|
||||||
|
void push_back(const T& item) { Add(item); }
|
||||||
|
|
||||||
|
void Insert(const T& item, size_t uiIndex, size_t nInsert = 1)
|
||||||
|
{
|
||||||
|
if ( nInsert == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
T* const pItem = Traits::Clone(item);
|
||||||
|
if ( pItem != NULL )
|
||||||
|
base::insert(this->begin() + uiIndex, nInsert, pItem);
|
||||||
|
|
||||||
|
for ( size_t i = 1; i < nInsert; ++i )
|
||||||
|
base::operator[](uiIndex + i) = Traits::Clone(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Insert(const T* pItem, size_t uiIndex)
|
||||||
|
{
|
||||||
|
base::insert(this->begin() + uiIndex, (T*)pItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Empty() { DoEmpty(); base::clear(); }
|
||||||
|
void Clear() { DoEmpty(); base::clear(); }
|
||||||
|
|
||||||
|
T* Detach(size_t uiIndex)
|
||||||
|
{
|
||||||
|
T* const p = base::operator[](uiIndex);
|
||||||
|
|
||||||
|
base::erase(this->begin() + uiIndex);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveAt(size_t uiIndex, size_t nRemove = 1)
|
||||||
|
{
|
||||||
|
wxCHECK_RET( uiIndex < size(), "bad index in RemoveAt()" );
|
||||||
|
|
||||||
|
for ( size_t i = 0; i < nRemove; ++i )
|
||||||
|
Traits::Free(base::operator[](uiIndex + i));
|
||||||
|
|
||||||
|
base::erase(this->begin() + uiIndex, this->begin() + uiIndex + nRemove);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sort(CMPFUNC fCmp) { base::Sort(fCmp); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void DoEmpty()
|
||||||
|
{
|
||||||
|
for ( size_t n = 0; n < size(); ++n )
|
||||||
|
Traits::Free(base::operator[](n));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoCopy(const wxBaseObjectArray& src)
|
||||||
|
{
|
||||||
|
reserve(src.size());
|
||||||
|
for ( size_t n = 0; n < src.size(); ++n )
|
||||||
|
Add(src[n]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// The public macros for declaration and definition of the dynamic arrays
|
// The public macros for declaration and definition of the dynamic arrays
|
||||||
@@ -530,9 +640,22 @@ private: \
|
|||||||
#define WX_DECLARE_EXPORTED_OBJARRAY(T, name) \
|
#define WX_DECLARE_EXPORTED_OBJARRAY(T, name) \
|
||||||
WX_DECLARE_USER_EXPORTED_OBJARRAY(T, name, WXDLLIMPEXP_CORE)
|
WX_DECLARE_USER_EXPORTED_OBJARRAY(T, name, WXDLLIMPEXP_CORE)
|
||||||
|
|
||||||
#define WX_DECLARE_OBJARRAY_WITH_DECL(T, name, decl) \
|
#define WX_DECLARE_OBJARRAY_WITH_DECL(T, name, classdecl) \
|
||||||
typedef T _wxObjArray##name; \
|
classdecl wxObjectArrayTraitsFor##name \
|
||||||
_WX_DECLARE_OBJARRAY(_wxObjArray##name, name, wxArrayPtrVoid, decl)
|
{ \
|
||||||
|
public: \
|
||||||
|
static T* Clone(const T& item); \
|
||||||
|
static void Free(T* p); \
|
||||||
|
}; \
|
||||||
|
typedef wxBaseObjectArray<T, wxObjectArrayTraitsFor##name> \
|
||||||
|
wxBaseObjectArrayFor##name; \
|
||||||
|
typedef int (wxCMPFUNC_CONV *CMPFUNC##T)(T **pItem1, T **pItem2); \
|
||||||
|
classdecl name : public wxBaseObjectArrayFor##name \
|
||||||
|
{ \
|
||||||
|
public: \
|
||||||
|
name() : wxBaseObjectArrayFor##name() { } \
|
||||||
|
name(const name& src) : wxBaseObjectArrayFor##name(src) { } \
|
||||||
|
}
|
||||||
|
|
||||||
#define WX_DECLARE_USER_EXPORTED_OBJARRAY(T, name, expmode) \
|
#define WX_DECLARE_USER_EXPORTED_OBJARRAY(T, name, expmode) \
|
||||||
WX_DECLARE_OBJARRAY_WITH_DECL(T, name, class expmode)
|
WX_DECLARE_OBJARRAY_WITH_DECL(T, name, class expmode)
|
||||||
|
Reference in New Issue
Block a user