diff --git a/include/wx/arrstr.h b/include/wx/arrstr.h index 1a62bef72b..cb5f986b35 100644 --- a/include/wx/arrstr.h +++ b/include/wx/arrstr.h @@ -95,6 +95,8 @@ public: wxBaseArray::Add(string, copies); return size() - copies; } + + const std::vector& AsVector() const { return *this; } }; // Unlike all the other sorted arrays, this one uses a comparison function @@ -240,6 +242,8 @@ public: } const wxString& Last() const { return const_cast(this)->Last(); } + // get all items as a vector + std::vector AsVector() const; // item management // Search the element in the array, starting from the beginning if diff --git a/interface/wx/arrstr.h b/interface/wx/arrstr.h index 6185e5ace8..a817eda4cf 100644 --- a/interface/wx/arrstr.h +++ b/interface/wx/arrstr.h @@ -32,10 +32,30 @@ countries); @endcode + When using a wxWidgets function returning an object of this class, you can + either use it as if it were a `std::vector`, as this class has + all vector methods, or actually convert it to such vector using its + AsVector(), e.g. - If you do use this class directly, it's recommended to prefer using its - `std::vector`-like methods instead of the legacy wxArray-like - ones. + @code + wxArrayString files; + wxDir::GetAllFiles("/some/path", &files); + + // Can use the usual accessors: + if ( !files.empty() ) { + auto first = files[0]; + auto total = files.size(); + ... + } + + // Can iterate over it like over a vector, too. + for ( const wxString& file: files ) { + ... + } + + // Or can just convert it to the "real" vector: + const std::vector& vec = files.AsVector(); + @endcode @library{wxbase} @category{containers} @@ -135,6 +155,25 @@ public: */ void Alloc(size_t nCount); + /** + Constructs a std::vector containing the same strings as this array. + + In @ref overview_container_std, this function actually returns a const + reference to this object itself, without making a copy, but in the + default/compatible build, it has to copy all the strings, making it + expensive to call for big arrays. + + Note that using it like this: + @code + const std::vector& vec = array.AsVector(); + @endcode + works in all builds as long as you don't need to modify the returned + vector and doesn't impose any extra overhead in the STL build. + + @since 3.3.0 + */ + std::vector AsVector() const; + /** Clears the array contents and frees memory. diff --git a/src/common/arrstr.cpp b/src/common/arrstr.cpp index 71b6a3c571..0d9600e29e 100644 --- a/src/common/arrstr.cpp +++ b/src/common/arrstr.cpp @@ -150,6 +150,14 @@ wxArrayString& wxArrayString::operator=(const wxArrayString& src) return *this; } +std::vector wxArrayString::AsVector() const +{ + if ( !m_pItems ) + return {}; + + return std::vector{m_pItems, m_pItems + m_nCount}; +} + void wxArrayString::Copy(const wxArrayString& src) { if ( src.m_nCount > ARRAY_DEFAULT_INITIAL_SIZE ) diff --git a/tests/arrays/arrays.cpp b/tests/arrays/arrays.cpp index 15dce0b0bc..c133a9245d 100644 --- a/tests/arrays/arrays.cpp +++ b/tests/arrays/arrays.cpp @@ -355,7 +355,7 @@ TEST_CASE("wxArrayString", "[dynarray]") CHECK( a9.size() == 5 ); } -TEST_CASE("wxArrayString::FromVector", "[dynarray][vector]") +TEST_CASE("wxArrayString::Vector", "[dynarray][vector]") { SECTION("wxString") { @@ -372,6 +372,14 @@ TEST_CASE("wxArrayString::FromVector", "[dynarray][vector]") REQUIRE( a.size() == 2 ); CHECK( a[1] == "fourth" ); } + + SECTION("AsVector") + { + wxArrayString a{"five", "six", "seven"}; + const std::vector& vec = a.AsVector(); + REQUIRE( vec.size() == 3 ); + CHECK( vec.at(2) == "seven" ); + } } TEST_CASE("wxSortedArrayString", "[dynarray]")