Skip to content

Commit

Permalink
Add support for initializer_list to wx dynamic arrays
Browse files Browse the repository at this point in the history
While these array classes are deprecated in the user code, they're still
used, for compatibility, in many places in wxWidgets API and allowing to
create them from initializer_list makes using it more ergonomic as it's
now possible to just pass an initializer list of items to fill the
control with, for example, instead of appending them one by one.

This is the equivalent of 4d62df4 (Add support for initializer_list
to wx dynamic arrays, 2023-03-02) from master.

See #23309.

Closes #23966.
  • Loading branch information
Lotendan authored and vadz committed Nov 7, 2023
1 parent a87c857 commit 425d945
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 0 deletions.
4 changes: 4 additions & 0 deletions docs/changes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,10 @@ Changes in behaviour which may result in build errors
3.2.4: (released 2024-??-??)
----------------------------

All:

- Allow creating wxArrays from std::initialized_list (Lotendan, #23966).

All (GUI):

- Fix refreshing multiple selection items in generic wxListCtrl.
Expand Down
12 changes: 12 additions & 0 deletions include/wx/arrstr.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
#if wxUSE_STD_CONTAINERS_COMPATIBLY
#include <vector>
#endif
#ifdef wxHAVE_INITIALIZER_LIST
#include <initializer_list>
#endif

// these functions are only used in STL build now but we define them in any
// case for compatibility with the existing code outside of the library which
Expand Down Expand Up @@ -83,6 +86,10 @@ class WXDLLIMPEXP_BASE wxArrayString : public wxArrayStringBase
wxArrayString(size_t sz, const char** a);
wxArrayString(size_t sz, const wchar_t** a);
wxArrayString(size_t sz, const wxString* a);
#ifdef wxHAVE_INITIALIZER_LIST
template<typename U>
wxArrayString(std::initializer_list<U> list) : wxArrayStringBase(list) { }
#endif

int Index(const wxString& str, bool bCase = true, bool bFromEnd = false) const;

Expand Down Expand Up @@ -184,6 +191,11 @@ class WXDLLIMPEXP_BASE wxArrayString
wxArrayString(size_t sz, const wxString* a);
// copy ctor
wxArrayString(const wxArrayString& array);
#ifdef wxHAVE_INITIALIZER_LIST
// list constructor
template<typename U>
wxArrayString(std::initializer_list<U> list) { Init(false); assign(list.begin(), list.end()); }
#endif
// assignment operator
wxArrayString& operator=(const wxArrayString& src);
// not virtual, this class should not be derived from
Expand Down
8 changes: 8 additions & 0 deletions include/wx/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,14 @@ typedef short int WXTYPE;
#endif
#endif /* HAVE_WOSTREAM */

#ifndef wxHAVE_INITIALIZER_LIST
#if __cplusplus >= 201103L
#define wxHAVE_INITIALIZER_LIST
#elif wxCHECK_VISUALC_VERSION(11)
#define wxHAVE_INITIALIZER_LIST
#endif
#endif /* wxHAVE_INITIALIZER_LIST */

/* ---------------------------------------------------------------------------- */
/* portable calling conventions macros */
/* ---------------------------------------------------------------------------- */
Expand Down
18 changes: 18 additions & 0 deletions include/wx/dynarray.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@

#include "wx/vector.h"

#ifdef wxHAVE_INITIALIZER_LIST
#include <initializer_list>
#endif

/*
This header defines legacy dynamic arrays and object arrays (i.e. arrays
which own their elements) classes.
Expand Down Expand Up @@ -105,6 +109,11 @@ class wxBaseArray : public wxVector<T>
: base_vec(first, last)
{ }

#ifdef wxHAVE_INITIALIZER_LIST
template<typename U>
wxBaseArray(std::initializer_list<U> list) : base_vec(list.begin(), list.end()) {}
#endif

void Empty() { this->clear(); }
void Clear() { this->clear(); }
void Alloc(size_t uiSize) { this->reserve(uiSize); }
Expand Down Expand Up @@ -495,6 +504,14 @@ class wxBaseObjectArray : private wxBaseArray<T*>
#define WX_DEFINE_USER_EXPORTED_TYPEARRAY_PTR(T, name, base, expdecl) \
WX_DEFINE_TYPEARRAY_WITH_DECL_PTR(T, name, base, class expdecl)

#ifdef wxHAVE_INITIALIZER_LIST
#define WX_DEFINE_CTOR_FROM_INIT_LIST(T, name, base, classdecl) \
template<typename U> \
name(std::initializer_list<U> list) : Base(list.begin(), list.end()) { }
#else
#define WX_DEFINE_CTOR_FROM_INIT_LIST(T, name, base, classdecl) // No support for initializer_list
#endif

// This is the only non-trivial macro, which actually defines the array class
// with the given name containing the elements of the specified type.
//
Expand All @@ -519,6 +536,7 @@ class wxBaseObjectArray : private wxBaseArray<T*>
name(size_t n, Base::const_reference v) : Base(n, v) { } \
template <class InputIterator> \
name(InputIterator first, InputIterator last) : Base(first, last) { } \
WX_DEFINE_CTOR_FROM_INIT_LIST(T, name, base, classdecl) \
}


Expand Down
8 changes: 8 additions & 0 deletions interface/wx/arrstr.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,14 @@ class wxArrayString : public wxArray
*/
wxArrayString(size_t sz, const wxString* arr);

/**
Constructs the container with the contents of the initializer_list @a list.
@since 3.2.4
*/
template<typename T>
wxArrayString(std::initializer_list<T> list);

/**
Destructor frees memory occupied by the array strings. For performance
reasons it is not virtual, so this class should not be derived from.
Expand Down
8 changes: 8 additions & 0 deletions interface/wx/dynarray.h
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,14 @@ class wxArray<T>
*/
wxObjArray(const wxObjArray& array);

/**
Constructs the container with the contents of the initializer_list @a list.
@since 3.2.4
*/
template<typename T>
wxArray(std::initializer_list<T> list);

/**
Performs a shallow array copy (i.e.\ doesn't copy the objects pointed to
even if the source array contains the items of pointer type).
Expand Down
25 changes: 25 additions & 0 deletions tests/arrays/arrays.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,21 @@ TEST_CASE("wxArrayString", "[dynarray]")
CHECK( a7.size() == 1 );

wxCLANG_WARNING_RESTORE(self-assign-overloaded)

#ifdef wxHAVE_INITIALIZER_LIST
wxArrayString a8( { wxT("dog"), wxT("human"), wxT("condor"), wxT("thermit"), wxT("alligator") } );
CHECK( a8.size() == 5 );
CHECK( a8[1] == "human" );
CHECK( a8[4] == "alligator" );

a8 = { wxT("Foo") }; // Test operator=
CHECK( a8.size() == 1 );
CHECK( a8[0] == "Foo" );

// Same test with std::initializer_list<std::string>
wxArrayString a9( { std::string("dog"), std::string("human"), std::string("condor"), std::string("thermit"), std::string("alligator") } );
CHECK( a9.size() == 5 );
#endif // wxHAVE_INITIALIZER_LIST
}

TEST_CASE("wxSortedArrayString", "[dynarray]")
Expand Down Expand Up @@ -584,6 +599,14 @@ TEST_CASE("wxObjArrayPtr", "[dynarray]")
CHECK( barptrs.size() == 0 );
}

#ifdef wxHAVE_INITIALIZER_LIST
#define TestArrayWithInitializerListOf(name) \
wxArray##name c({1,2,3}); \
CHECK(c.size() == 3);
#else
#define TestArrayWithInitializerListOf(name) // No support for initializer_list
#endif

#define TestArrayOf(name) \
\
TEST_CASE("wxDynArray::" #name, "[dynarray]") \
Expand Down Expand Up @@ -623,6 +646,8 @@ TEST_CASE("wxDynArray::" #name, "[dynarray]") \
CHECK( b.Index( 5 ) == 2 ); \
CHECK( b.Index( 6 ) == wxNOT_FOUND ); \
CHECK( b.Index( 17 ) == 3 ); \
\
TestArrayWithInitializerListOf(name) \
}

TestArrayOf(UShort)
Expand Down

0 comments on commit 425d945

Please sign in to comment.