diff --git a/include/wx/dynarray.h b/include/wx/dynarray.h index e355fb316e..1d5801f8cb 100644 --- a/include/wx/dynarray.h +++ b/include/wx/dynarray.h @@ -381,7 +381,7 @@ public: const size_t nOldSize = size(); if ( pItem != nullptr ) - base::insert(this->end(), nInsert, pItem); + base::insert(base::end(), nInsert, pItem); for ( size_t i = 1; i < nInsert; i++ ) base::operator[](nOldSize + i) = Traits::Clone(item); @@ -402,7 +402,7 @@ public: T* const pItem = Traits::Clone(item); if ( pItem != nullptr ) - base::insert(this->begin() + uiIndex, nInsert, pItem); + base::insert(base::begin() + uiIndex, nInsert, pItem); for ( size_t i = 1; i < nInsert; ++i ) base::operator[](uiIndex + i) = Traits::Clone(item); @@ -410,7 +410,7 @@ public: void Insert(const T* pItem, size_t uiIndex) { - base::insert(this->begin() + uiIndex, const_cast(pItem)); + base::insert(base::begin() + uiIndex, const_cast(pItem)); } void Empty() { DoEmpty(); base::clear(); } @@ -420,7 +420,7 @@ public: { T* const p = base::operator[](uiIndex); - base::erase(this->begin() + uiIndex); + base::erase(base::begin() + uiIndex); return p; } @@ -431,11 +431,42 @@ public: for ( size_t i = 0; i < nRemove; ++i ) Traits::Free(base::operator[](uiIndex + i)); - base::erase(this->begin() + uiIndex, this->begin() + uiIndex + nRemove); + base::erase(base::begin() + uiIndex, base::begin() + uiIndex + nRemove); } void Sort(CMPFUNC fCmp) { base::Sort(fCmp); } + void swap(wxBaseObjectArray& other) { base::swap(other); } + + // Provide a way to iterate over the stored objects using range-based for. + class ObjectIterator + { + public: + using base_iter = typename base::const_iterator; + + using value_type = T; + using reference = T&; + using pointer = T*; + using difference_type = typename std::iterator_traits::difference_type; + using iterator_category = std::random_access_iterator_tag; + + ObjectIterator() = default; + ObjectIterator(base_iter const& it) : m_it(it) { } + + bool operator==(ObjectIterator const& other) const { return m_it == other.m_it; } + bool operator!=(ObjectIterator const& other) const { return m_it != other.m_it; } + + reference operator*() const { return **m_it; } + ObjectIterator& operator++() { ++m_it; return *this; } + ObjectIterator& operator--() { --m_it; return *this; } + + private: + typename base::const_iterator m_it; + }; + + wxNODISCARD ObjectIterator begin() const { return base::begin(); } + wxNODISCARD ObjectIterator end() const { return base::end(); } + private: void DoEmpty() { diff --git a/tests/arrays/arrays.cpp b/tests/arrays/arrays.cpp index c133a9245d..6f7277d22c 100644 --- a/tests/arrays/arrays.cpp +++ b/tests/arrays/arrays.cpp @@ -598,12 +598,33 @@ TEST_CASE("wxObjArray", "[dynarray]") CHECK( bars.GetCount() == 0 ); CHECK( Bar::GetNumber() == 1 ); - bars.Add(new Bar(wxT("first bar in array"))); + const wxString firstName(wxT("first bar in array")); + bars.Add(new Bar(firstName)); bars.Add(bar, 2); + // Test that range for works with wxObjArray. + int count = 0; + for ( const auto& bar : bars ) + { + if ( !count ) + CHECK( bar.GetName() == firstName ); + + ++count; + } + CHECK( count == 3 ); + CHECK( bars.GetCount() == 3 ); CHECK( Bar::GetNumber() == 4 ); + ArrayBars tmp; + bars.swap(tmp); + CHECK( bars.size() == 0 ); + CHECK( Bar::GetNumber() == 4 ); + + bars.swap(tmp); + CHECK( bars.size() == 3 ); + CHECK( Bar::GetNumber() == 4 ); + bars.RemoveAt(1, bars.GetCount() - 1); CHECK( bars.GetCount() == 1 );