Fix wrong function pointer casts in dynamic arrays code

Don't cast function pointers of incompatible types, this resulted in gcc
8 -Wcast-function-type warnings and could hide real errors.

To fix this, overload wxBaseArray::Sort() to accept either the "legacy"
sort function compatible with qsort() or a function compatible with
std::sort(), as it seems both variants could be used before. Also make
the type of the latter function customizable via a new optional Sorter
template parameter in wxBaseArray in order to allow wxSortedArrayString
to specify its own variant of it, taking (const) references instead of
values.

This complicates things, but should preserve compatibility while being
type-safe and, also, allows to simplify _WX_DEFINE_SORTED_TYPEARRAY_2 by
not passing the sort function signature to it any more.
This commit is contained in:
Vadim Zeitlin 2018-06-03 23:27:38 +02:00
parent 6294511a4e
commit 93edcaef20
2 changed files with 39 additions and 24 deletions

View File

@ -80,9 +80,25 @@ public:
}
};
_WX_DEFINE_SORTED_TYPEARRAY_2(wxString, wxSortedArrayStringBase,
wxArrayStringBase, = wxStringSortAscending,
class WXDLLIMPEXP_BASE, wxArrayString::CompareFunction);
// Unlike all the other sorted arrays, this one uses a comparison function
// taking objects by reference rather than value, so define a special functor
// wrapping it.
class wxSortedArrayString_SortFunction
{
public:
typedef int (wxCMPFUNC_CONV *CMPFUNC)(const wxString&, const wxString&);
explicit wxSortedArrayString_SortFunction(CMPFUNC f) : m_f(f) { }
bool operator()(const wxString& s1, const wxString& s2)
{ return m_f(s1, s2) < 0; }
private:
CMPFUNC m_f;
};
typedef wxBaseSortedArray<wxString, wxSortedArrayString_SortFunction>
wxSortedArrayStringBase;
class WXDLLIMPEXP_BASE wxSortedArrayString : public wxSortedArrayStringBase
{

View File

@ -75,13 +75,11 @@ private:
CMPFUNC m_f;
};
template <typename T>
template <typename T, typename Sorter = wxSortedArray_SortFunction<T> >
class wxBaseArray : public wxVector<T>
{
typedef wxSortedArray_SortFunction<T> Predicate;
public:
typedef typename Predicate::CMPFUNC SCMPFUNC;
typedef typename Sorter::CMPFUNC SCMPFUNC;
typedef typename wxArray_SortFunction<T>::CMPFUNC CMPFUNC;
typedef wxVector<T> base_vec;
@ -158,7 +156,7 @@ public:
int Index(T lItem, SCMPFUNC fnCompare) const
{
Predicate p(fnCompare);
Sorter p(fnCompare);
const_iterator i = std::lower_bound(this->begin(), this->end(), lItem, p);
return i != this->end() && !p(lItem, *i) ? (int)(i - this->begin())
: wxNOT_FOUND;
@ -166,7 +164,7 @@ public:
size_t IndexForInsert(T lItem, SCMPFUNC fnCompare) const
{
Predicate p(fnCompare);
Sorter p(fnCompare);
const_iterator i = std::lower_bound(this->begin(), this->end(), lItem, p);
return i - this->begin();
}
@ -208,7 +206,7 @@ public:
void Sort(SCMPFUNC fCmp)
{
Predicate p(fCmp);
Sorter p(fCmp);
std::sort(this->begin(), this->end(), p);
}
};
@ -222,31 +220,34 @@ public:
// cannot handle types with size greater than pointer because of sorting
// ----------------------------------------------------------------------------
#define _WX_DEFINE_SORTED_TYPEARRAY_2(T, name, base, defcomp, classexp, comptype)\
typedef wxBaseSortedArray<T, comptype> wxBaseSortedArrayFor##name; \
#define _WX_DEFINE_SORTED_TYPEARRAY_2(T, name, base, defcomp, classexp) \
typedef wxBaseSortedArray<T> wxBaseSortedArrayFor##name; \
classexp name : public wxBaseSortedArrayFor##name \
{ \
public: \
name(comptype fn defcomp) : wxBaseSortedArrayFor##name(fn) { } \
name(wxBaseSortedArrayFor##name::SCMPFUNC fn defcomp) \
: wxBaseSortedArrayFor##name(fn) { } \
}
template <typename T, typename Cmp>
class wxBaseSortedArray : public wxBaseArray<T>
template <typename T, typename Sorter = wxSortedArray_SortFunction<T> >
class wxBaseSortedArray : public wxBaseArray<T, Sorter>
{
public:
explicit wxBaseSortedArray(Cmp fn) : m_fnCompare(fn) { }
typedef typename Sorter::CMPFUNC SCMPFUNC;
explicit wxBaseSortedArray(SCMPFUNC fn) : m_fnCompare(fn) { }
wxBaseSortedArray& operator=(const wxBaseSortedArray& src)
{
wxBaseArray<T>::operator=(src);
wxBaseArray<T, Sorter>::operator=(src);
m_fnCompare = src.m_fnCompare;
return *this;
}
size_t IndexForInsert(T item) const
{
return this->wxBaseArray<T>::IndexForInsert(item, m_fnCompare);
return this->wxBaseArray<T, Sorter>::IndexForInsert(item, m_fnCompare);
}
void AddAt(T item, size_t index)
@ -256,7 +257,7 @@ public:
size_t Add(T item)
{
return this->wxBaseArray<T>::Add(item, m_fnCompare);
return this->wxBaseArray<T, Sorter>::Add(item, m_fnCompare);
}
void push_back(T item)
@ -265,7 +266,7 @@ public:
}
private:
Cmp m_fnCompare;
SCMPFUNC m_fnCompare;
};
@ -572,9 +573,8 @@ private:
#define WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY(T, name, base, expmode) \
typedef T _wxArray##name; \
typedef int (CMPFUNC_CONV *SCMPFUNC##name)(T pItem1, T pItem2); \
_WX_DEFINE_SORTED_TYPEARRAY_2(_wxArray##name, name, base, \
wxARRAY_EMPTY, class expmode, SCMPFUNC##name)
wxARRAY_EMPTY, class expmode)
// ----------------------------------------------------------------------------
// WX_DEFINE_SORTED_TYPEARRAY_CMP: exactly the same as above but the comparison
@ -599,9 +599,8 @@ private:
#define WX_DEFINE_SORTED_USER_EXPORTED_TYPEARRAY_CMP(T, cmpfunc, name, base, \
expmode) \
typedef T _wxArray##name; \
typedef int (CMPFUNC_CONV *SCMPFUNC##name)(T pItem1, T pItem2); \
_WX_DEFINE_SORTED_TYPEARRAY_2(_wxArray##name, name, base, = cmpfunc, \
class expmode, SCMPFUNC##name)
class expmode)
// ----------------------------------------------------------------------------
// WX_DECLARE_OBJARRAY(T, name): this macro generates a new array class