From bbb5d1b6374153125ad6a46369a251a4f99a512b Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 10 Apr 2023 15:34:20 +0100 Subject: [PATCH 01/10] Deprecate useless wxResourceCache class This is just a trivial wrapper for wxList, which is itself obsolete, so deprecate it and schedule for removal in wx 3.6. Also move it entirely inline and don't export it from the DLL any longer both because this avoids generating any code for it if it's not used (as should be the case for 99.99% of wx applications) and because we currently can't use wxDEPRECATED_MSG() and WXDLLIMPEXP_CORE together in the same declaration. --- include/wx/gdicmn.h | 19 +++++++++++++++++-- src/common/gdicmn.cpp | 11 ----------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/include/wx/gdicmn.h b/include/wx/gdicmn.h index 058776ff8d..2de48183c9 100644 --- a/include/wx/gdicmn.h +++ b/include/wx/gdicmn.h @@ -930,16 +930,31 @@ private: wxStringToColourHashMap *m_map; }; -class WXDLLIMPEXP_CORE wxResourceCache: public wxList +#if WXWIN_COMPATIBILITY_3_2 + +class +wxDEPRECATED_MSG("Use wxList directly or just a standard container") +wxResourceCache : public wxList { public: wxResourceCache() { } #if !wxUSE_STD_CONTAINERS wxResourceCache(unsigned int keyType) : wxList(keyType) { } #endif - virtual ~wxResourceCache(); + virtual ~wxResourceCache() + { + wxList::compatibility_iterator node = GetFirst (); + while (node) { + wxObject *item = (wxObject *)node->GetData(); + delete item; + + node = node->GetNext (); + } + } }; +#endif // WXWIN_COMPATIBILITY_3_2 + // --------------------------------------------------------------------------- // global variables // --------------------------------------------------------------------------- diff --git a/src/common/gdicmn.cpp b/src/common/gdicmn.cpp index 213095d779..77a79438f4 100644 --- a/src/common/gdicmn.cpp +++ b/src/common/gdicmn.cpp @@ -954,14 +954,3 @@ wxSize wxGetDisplayPPI() { return wxDisplay().GetPPI(); } - -wxResourceCache::~wxResourceCache () -{ - wxList::compatibility_iterator node = GetFirst (); - while (node) { - wxObject *item = (wxObject *)node->GetData(); - delete item; - - node = node->GetNext (); - } -} From 1e9b84cd27f7899d33b88f1d868afe5b91ac68ad Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 10 Apr 2023 15:38:29 +0100 Subject: [PATCH 02/10] Remove unnecessary inclusion from wxPropGrid header This isn't needed any longer since the changes of 4c463c416d (Use std::vector instead of wxVector in wxPropertyGrid, 2023-01-22). No real changes. --- include/wx/propgrid/propgriddefs.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/wx/propgrid/propgriddefs.h b/include/wx/propgrid/propgriddefs.h index 54002be36c..0ef842a752 100644 --- a/include/wx/propgrid/propgriddefs.h +++ b/include/wx/propgrid/propgriddefs.h @@ -23,9 +23,6 @@ class WXDLLIMPEXP_FWD_CORE wxSize; class WXDLLIMPEXP_FWD_CORE wxFont; #include -#if wxUSE_STD_CONTAINERS -#include -#endif // wxUSE_STD_CONTAINERS // ----------------------------------------------------------------------- From 3a96c34e1277a3b7a0bb4a58bef9226b953b4fa7 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 10 Apr 2023 15:41:11 +0100 Subject: [PATCH 03/10] Make wxStack an alias template instead of a macro in STL build Just avoid the unnecessary use of the preprocessor. --- include/wx/stack.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/wx/stack.h b/include/wx/stack.h index b4e8ed2f8a..91bcd392de 100644 --- a/include/wx/stack.h +++ b/include/wx/stack.h @@ -16,7 +16,9 @@ #if wxUSE_STD_CONTAINERS #include -#define wxStack std::stack + +template +using wxStack = std::stack; #else // !wxUSE_STD_CONTAINERS From de1dca5ff1c230f1c6d2db9c35e09b67d13cd3fe Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 10 Apr 2023 15:44:52 +0100 Subject: [PATCH 04/10] Remove an unnecessary test for wxUSE_STD_CONTAINERS Remove the extra initialization which was supposed to avoid a compiler warning that doesn't seem to happen any more. --- src/common/cmdproc.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/common/cmdproc.cpp b/src/common/cmdproc.cpp index f92cd14f7d..42faef0f05 100644 --- a/src/common/cmdproc.cpp +++ b/src/common/cmdproc.cpp @@ -163,11 +163,7 @@ bool wxCommandProcessor::Undo() bool wxCommandProcessor::Redo() { wxCommand *redoCommand = nullptr; - wxList::compatibility_iterator redoNode -#if !wxUSE_STD_CONTAINERS - = nullptr // just to avoid warnings -#endif // !wxUSE_STD_CONTAINERS - ; + wxList::compatibility_iterator redoNode; if ( m_currentCommand ) { From e273d45c9b886c59583614aff8560987047d39fb Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 10 Apr 2023 16:06:04 +0100 Subject: [PATCH 05/10] Enable use of the standard container classes by default This is mostly, even if not completely, compatible with the previous default build using wxUSE_STD_CONTAINERS=0, so try enabling this by default again. Hopefully it should work better now than the last time we tried it, see 01871bf642 (Add wxUSE_STD_CONTAINERS and turn it on by default., 2011-03-30) and the subsequent 7311debd0d (Don't use the standard containers by default., 2011-05-13). See #22718. --- build/cmake/options.cmake | 2 +- configure | 9 ++------- configure.in | 7 +------ include/wx/android/setup.h | 8 ++++---- include/wx/gtk/setup.h | 8 ++++---- include/wx/msw/setup.h | 8 ++++---- include/wx/osx/setup.h | 8 ++++---- include/wx/setup_inc.h | 8 ++++---- include/wx/univ/setup.h | 8 ++++---- 9 files changed, 28 insertions(+), 38 deletions(-) diff --git a/build/cmake/options.cmake b/build/cmake/options.cmake index 8c20872c2b..cdb0bf9f2e 100644 --- a/build/cmake/options.cmake +++ b/build/cmake/options.cmake @@ -84,7 +84,7 @@ wx_option(wxUSE_NO_RTTI "disable RTTI support" OFF) wx_option(wxUSE_STD_IOSTREAM "use standard C++ streams" ON) wx_option(wxUSE_STL "use standard C++ classes for everything" OFF) set(wxTHIRD_PARTY_LIBRARIES ${wxTHIRD_PARTY_LIBRARIES} wxUSE_STL "use C++ STL classes") -wx_dependent_option(wxUSE_STD_CONTAINERS "use standard C++ container classes" ON "wxUSE_STL" OFF) +wx_option(wxUSE_STD_CONTAINERS "use standard C++ container classes" ON) wx_option(wxUSE_UNICODE_UTF8 "use UTF-8 representation for strings" OFF) wx_dependent_option(wxUSE_UTF8_LOCALE_ONLY "only support UTF-8 locales in UTF-8 build" ON "wxUSE_UNICODE_UTF8" OFF) diff --git a/configure b/configure index b602b6ce47..d3825439ee 100755 --- a/configure +++ b/configure @@ -2086,7 +2086,7 @@ Optional Features: --disable-shared create static library instead of shared --enable-cxx11 obsolete option doing nothing --enable-stl use standard C++ classes for everything - --enable-std_containers use standard C++ container classes + --disable-std_containers disable use of standard C++ container classes --disable-std_iostreams disable use of standard C++ stream classes --enable-std_string_conv_in_wxstring provide implicit conversion to std::string in wxString --disable-unsafe_conv_in_wxstring disable unsafe implicit conversions in wxString @@ -4023,8 +4023,6 @@ esac DEFAULT_wxUSE_ALL_FEATURES=yes -DEFAULT_wxUSE_STD_CONTAINERS=no - DEFAULT_wxUSE_DMALLOC=no DEFAULT_wxUSE_LIBCURL=auto DEFAULT_wxUSE_LIBGNOMEVFS=no @@ -5578,11 +5576,8 @@ fi eval "$wx_cv_use_stl" -if test "$wxUSE_STL" = "yes"; then - DEFAULT_wxUSE_STD_CONTAINERS=yes -fi - enablestring= + enablestring=disable defaultval= if test -z "$defaultval"; then if test x"$enablestring" = xdisable; then diff --git a/configure.in b/configure.in index 2ad1197b0b..b8149d5340 100644 --- a/configure.in +++ b/configure.in @@ -310,8 +310,6 @@ dnl wxUSE_ALL_FEATURES which is the only which has to be set to "yes" by dnl default) DEFAULT_wxUSE_ALL_FEATURES=yes -DEFAULT_wxUSE_STD_CONTAINERS=no - dnl libraries disabled by default or requiring some special handling DEFAULT_wxUSE_DMALLOC=no DEFAULT_wxUSE_LIBCURL=auto @@ -642,10 +640,7 @@ WX_ARG_DISABLE(shared, [ --disable-shared create static library inst AC_ARG_ENABLE(cxx11, [ --enable-cxx11 obsolete option doing nothing]) AC_ARG_WITH(cxx, [ --with-cxx=11|14|17|20 use the given C++ dialect], [wxWITH_CXX="$withval"]) WX_ARG_ENABLE(stl, [ --enable-stl use standard C++ classes for everything], wxUSE_STL) -if test "$wxUSE_STL" = "yes"; then - DEFAULT_wxUSE_STD_CONTAINERS=yes -fi -WX_ARG_ENABLE(std_containers,[ --enable-std_containers use standard C++ container classes], wxUSE_STD_CONTAINERS) +WX_ARG_DISABLE(std_containers,[ --disable-std_containers disable use of standard C++ container classes], wxUSE_STD_CONTAINERS) WX_ARG_DISABLE(std_iostreams,[ --disable-std_iostreams disable use of standard C++ stream classes], wxUSE_STD_IOSTREAM) WX_ARG_ENABLE(std_string_conv_in_wxstring, [ --enable-std_string_conv_in_wxstring provide implicit conversion to std::string in wxString], wxUSE_STD_STRING_CONV_IN_WXSTRING) WX_ARG_DISABLE(unsafe_conv_in_wxstring, [ --disable-unsafe_conv_in_wxstring disable unsafe implicit conversions in wxString], wxUSE_UNSAFE_WXSTRING_CONV) diff --git a/include/wx/android/setup.h b/include/wx/android/setup.h index 9b8b458969..4f9417c61c 100644 --- a/include/wx/android/setup.h +++ b/include/wx/android/setup.h @@ -283,11 +283,11 @@ // Use standard C++ containers to implement all wx container classes. // -// Default is 0 for compatibility reasons. +// Default is 1. // -// Recommended setting: 1 unless compatibility with the official wxWidgets -// build and/or the existing code is a concern. -#define wxUSE_STD_CONTAINERS 0 +// Recommended setting: 1 unless you really need to set it to 0 to preserve +// compatibility with the existing code. +#define wxUSE_STD_CONTAINERS 1 // Use standard C++ streams if 1 instead of wx streams in some places. If // disabled, wx streams are used instead. diff --git a/include/wx/gtk/setup.h b/include/wx/gtk/setup.h index fd554c0aba..3b3080bb6e 100644 --- a/include/wx/gtk/setup.h +++ b/include/wx/gtk/setup.h @@ -284,11 +284,11 @@ // Use standard C++ containers to implement all wx container classes. // -// Default is 0 for compatibility reasons. +// Default is 1. // -// Recommended setting: 1 unless compatibility with the official wxWidgets -// build and/or the existing code is a concern. -#define wxUSE_STD_CONTAINERS 0 +// Recommended setting: 1 unless you really need to set it to 0 to preserve +// compatibility with the existing code. +#define wxUSE_STD_CONTAINERS 1 // Use standard C++ streams if 1 instead of wx streams in some places. If // disabled, wx streams are used instead. diff --git a/include/wx/msw/setup.h b/include/wx/msw/setup.h index 112f62f7ec..c6bb17c86b 100644 --- a/include/wx/msw/setup.h +++ b/include/wx/msw/setup.h @@ -284,11 +284,11 @@ // Use standard C++ containers to implement all wx container classes. // -// Default is 0 for compatibility reasons. +// Default is 1. // -// Recommended setting: 1 unless compatibility with the official wxWidgets -// build and/or the existing code is a concern. -#define wxUSE_STD_CONTAINERS 0 +// Recommended setting: 1 unless you really need to set it to 0 to preserve +// compatibility with the existing code. +#define wxUSE_STD_CONTAINERS 1 // Use standard C++ streams if 1 instead of wx streams in some places. If // disabled, wx streams are used instead. diff --git a/include/wx/osx/setup.h b/include/wx/osx/setup.h index f5619fad6f..630fd17ff7 100644 --- a/include/wx/osx/setup.h +++ b/include/wx/osx/setup.h @@ -290,11 +290,11 @@ // Use standard C++ containers to implement all wx container classes. // -// Default is 0 for compatibility reasons. +// Default is 1. // -// Recommended setting: 1 unless compatibility with the official wxWidgets -// build and/or the existing code is a concern. -#define wxUSE_STD_CONTAINERS 0 +// Recommended setting: 1 unless you really need to set it to 0 to preserve +// compatibility with the existing code. +#define wxUSE_STD_CONTAINERS 1 // Use standard C++ streams if 1 instead of wx streams in some places. If // disabled, wx streams are used instead. diff --git a/include/wx/setup_inc.h b/include/wx/setup_inc.h index 63198eb5bc..5873b167fa 100644 --- a/include/wx/setup_inc.h +++ b/include/wx/setup_inc.h @@ -280,11 +280,11 @@ // Use standard C++ containers to implement all wx container classes. // -// Default is 0 for compatibility reasons. +// Default is 1. // -// Recommended setting: 1 unless compatibility with the official wxWidgets -// build and/or the existing code is a concern. -#define wxUSE_STD_CONTAINERS 0 +// Recommended setting: 1 unless you really need to set it to 0 to preserve +// compatibility with the existing code. +#define wxUSE_STD_CONTAINERS 1 // Use standard C++ streams if 1 instead of wx streams in some places. If // disabled, wx streams are used instead. diff --git a/include/wx/univ/setup.h b/include/wx/univ/setup.h index 442cd570e1..0fa97a426d 100644 --- a/include/wx/univ/setup.h +++ b/include/wx/univ/setup.h @@ -283,11 +283,11 @@ // Use standard C++ containers to implement all wx container classes. // -// Default is 0 for compatibility reasons. +// Default is 1. // -// Recommended setting: 1 unless compatibility with the official wxWidgets -// build and/or the existing code is a concern. -#define wxUSE_STD_CONTAINERS 0 +// Recommended setting: 1 unless you really need to set it to 0 to preserve +// compatibility with the existing code. +#define wxUSE_STD_CONTAINERS 1 // Use standard C++ streams if 1 instead of wx streams in some places. If // disabled, wx streams are used instead. From b934a6f27e9c7ed46419f988c1fad3c55f126a15 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 10 Apr 2023 18:50:27 +0100 Subject: [PATCH 06/10] Add special define allowing to check for gcc 4.8 This will allow to find all the places with the workarounds for this ancient compiler version more easily in the future, when we drop support for it. --- include/wx/compiler.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/include/wx/compiler.h b/include/wx/compiler.h index 30a904c2ef..d95110fced 100644 --- a/include/wx/compiler.h +++ b/include/wx/compiler.h @@ -80,8 +80,15 @@ #if __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 4) #error "This clang version is not supported any longer (at least clang 3.4 required)." #endif - #elif !wxCHECK_GCC_VERSION(4, 8) - #error "This gcc version is not supported any longer (at least gcc 4.8 required)." + #else + #if !wxCHECK_GCC_VERSION(4, 8) + #error "This gcc version is not supported any longer (at least gcc 4.8 required, gcc 6 or later recommended)." + #endif + + /* Define a special symbol used to work around 4.8 problems. */ + #if __GNUC__ == 4 && __GNUC_MINOR__ == 8 + #define wxGCC_4_8 + #endif #endif #else #define wxCHECK_GCC_VERSION( major, minor ) 0 From 50261bb88f47e264f699fff4e6f41b792a086464 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 10 Apr 2023 18:51:12 +0100 Subject: [PATCH 07/10] Disable use of std::unordered_map<> with gcc 4.8 for wx hash maps Due to a bug in gcc 4.8 standard library, inheriting from the standard class doesn't work, so we can't use it as the base class for our own containers with this compiler. --- include/wx/hashmap.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/include/wx/hashmap.h b/include/wx/hashmap.h index 4f9316b51b..2cd6227fe1 100644 --- a/include/wx/hashmap.h +++ b/include/wx/hashmap.h @@ -14,16 +14,22 @@ #include "wx/string.h" #include "wx/wxcrt.h" -#if wxUSE_STD_CONTAINERS +// wxUSE_STD_CONTAINERS can't be used with gcc 4.8 due to a bug in its standard +// library (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56278) which was fixed +// a very long time ago but is still present in the latest available versions +// of this compiler in Ubuntu and RHEL, so don't use the standard class with it. +#if !wxUSE_STD_CONTAINERS || defined(wxGCC_4_8) + #define wxNEEDS_WX_HASH_MAP +#endif + +#ifndef wxNEEDS_WX_HASH_MAP #include #define _WX_DECLARE_HASH_MAP( KEY_T, VALUE_T, HASH_T, KEY_EQ_T, CLASSNAME, CLASSEXP ) \ typedef std::unordered_map< KEY_T, VALUE_T, HASH_T, KEY_EQ_T > CLASSNAME -#else // !wxUSE_STD_CONTAINERS - -#define wxNEEDS_WX_HASH_MAP +#else // wxNEEDS_WX_HASH_MAP #include // for ptrdiff_t From 3335be13628e5baeb86673899930a77d852fddbc Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 10 Apr 2023 21:27:37 +0200 Subject: [PATCH 08/10] Document WX_DECLARE_LIST and WX_DEFINE_LIST macros Even though they're deprecated, they should still be documented, just as similar WX_DECLARE_OBJARRAY and WX_DEFINE_OBJARRAY are. --- interface/wx/list.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/interface/wx/list.h b/interface/wx/list.h index 8c9e724ef3..1215e031b6 100644 --- a/interface/wx/list.h +++ b/interface/wx/list.h @@ -460,3 +460,19 @@ public: void SetData(T* data); }; +/** + This macro declares a new legacy linked list container named @a name and + containing pointers to the objects of type @e T. + + You must use the WX_DEFINE_LIST() macro to define the class declared by + this macro. +*/ +#define WX_DECLARE_LIST(T, name) + +/** + This macro define a new legacy linked list container named @a name. + + You must use WX_DECLARE_LIST() macro to declare the list class before + defining it. +*/ +#define WX_DEFINE_LIST(T, name) From 89e4f51f62616f4d4e9b0f372247bef4df7d47d3 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 10 Apr 2023 19:18:06 +0100 Subject: [PATCH 09/10] Update documentation after setting wxUSE_STD_CONTAINERS=1 Explain that the legacy container classes now inherit from the standard classes by default and also how to update the existing code to compile when using standard library-based implementations. --- docs/changes.txt | 5 + docs/doxygen/overviews/container.h | 170 +++++++++++++++-------------- interface/wx/arrstr.h | 22 ++-- interface/wx/dynarray.h | 3 + interface/wx/hashmap.h | 12 +- interface/wx/hashset.h | 11 +- interface/wx/list.h | 27 +++-- 7 files changed, 137 insertions(+), 113 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index 6c4a7709da..e409062eeb 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -87,6 +87,11 @@ Changes in behaviour which may result in build errors - Building with wxUSE_UNICODE=0 is not supported any longer. +- wxUSE_STD_CONTAINERS is now set to 1 by default, see "Container Classes" + overview in the manual for the description of the changes this may require in + the existing code. Alternatively, explicitly set wxUSE_STD_CONTAINERS=0 when + compiling the library to preserve full compatibility with the old versions. + - wxMotif and wxGTK1 ports have been removed, please use wxWidgets 3.2 if you still need them. diff --git a/docs/doxygen/overviews/container.h b/docs/doxygen/overviews/container.h index fb76209eb5..8278ffb34a 100644 --- a/docs/doxygen/overviews/container.h +++ b/docs/doxygen/overviews/container.h @@ -14,34 +14,30 @@ For historical reasons, wxWidgets uses custom container classes internally. This was unfortunately unavoidable during a long time when the standard library wasn't widely available and can't be easily changed even now that it is for -compatibility reasons. If you are building your own version of the library and -don't care about compatibility nor slight (less than 5%) size penalty imposed -by the use of STL classes, you may choose to use the "STL" build of wxWidgets -in which these custom classes are replaced with their standard counterparts and -only read the section @ref overview_container_std explaining how to do it. +compatibility reasons. However, starting from version 3.3.0 these custom +container classes are implemented in terms of the standard library classes by +default and so are mostly interoperable with them. -Otherwise you will need to know about the custom wxWidgets container classes -such as wxList and wxArray if only to use wxWidgets functions that work -with them, e.g. wxWindow::GetChildren(), and you should find the information -about using these classes below useful. +This means that even if some wxWidgets function is documented as taking or +returning a legacy container such as wxList or wxArray, you can work with +them as if they were just `std::list` or `std::vector`. For example, +wxWidgets::GetChildren() is documented as returning a `wxWindowList`, which +inherits from `std::list` and so can be used as such, e.g. -Notice that we recommend that you use standard classes directly in your own -code instead of the container classes provided by wxWidgets in any case as the -standard classes are easier to use and may also be safer because of extra -run-time checks they may perform as well as more efficient. +@code + const auto& children = someFrame->GetChildren(); + auto it = std::find(children.begin(), children.end(), someWindow); + if ( it != children.end() ) + // ... do something with this window ... +@endcode -Finally notice that recent versions of wxWidgets also provide standard-like -classes such as wxVector, wxStack or wxDList which can be used exactly -like the std::vector, std::stack and std::list, respectively, and -actually are just typedefs for the corresponding types if wxWidgets is compiled -in STL mode. These classes could be useful if you wish to avoid the use of the -standard library in your code for some reason. - -To summarize, you should use the standard container classes such as -std::vector and std::list if possible and wxVector or wxDList if -it isn't and only use legacy wxWidgets containers such as wxArray and -wxList when you must, i.e. when you use a wxWidgets function taking or -returning a container of such type. +You may still need to create wxWidgets containers to pass them to some +wxWidgets function, e.g. wxDir::GetAllFiles() requires a wxArrayString to be +passed in. However in this case you may still the object as if it were just a +`std::vector` and, other than that, there is no reason to use the +container classes provided by wxWidgets anywhere in the new code, they only +exist for backwards compatibility and standard library classes should be used +by the application. @see @ref group_class_containers @@ -49,81 +45,95 @@ returning a container of such type. @section overview_container_legacy Legacy Classes -The list classes in wxWidgets are doubly-linked lists which may either own the -objects they contain (meaning that the list deletes the object when it is -removed from the list or the list itself is destroyed) or just store the -pointers depending on whether or not you called wxList::DeleteContents() -method. +This section contains a brief overview of the legacy container classes and is +mostly useful if you need to maintain an existing code base using them -- none +of this is really necessary to know if you follow the advice above and treat +all wxWidgets containers as if they were standard containers. -Dynamic arrays resemble C arrays but with two important differences: they -provide run-time range checking in debug builds and they automatically expand -the allocated memory when there is no more space for new items. They come in -two sorts: the "plain" arrays which store either built-in types such as "char", -"int" or "bool" or the pointers to arbitrary objects, or "object arrays" which -own the object pointers to which they store. - -For the same portability reasons, the container classes implementation in -wxWidgets don't use templates, but are rather based on C preprocessor i.e. are -implemented using the macros: WX_DECLARE_LIST() and WX_DEFINE_LIST() for the -linked lists and WX_DECLARE_ARRAY(), WX_DECLARE_OBJARRAY() and -WX_DEFINE_OBJARRAY() for the dynamic arrays. +All these classes use macro-based machinery to define type-safe classes based +on the generic implementation. Generally speaking, this consists of using one +macro to declare a particular "instantiation" and then another one to actually +define it, e.g. WX_DECLARE_LIST() and WX_DEFINE_LIST() for the linked lists or +WX_DECLARE_OBJARRAY() and WX_DEFINE_OBJARRAY() for the arrays containing +objects. The array classes storing primitive types, such as `int`, don't need +to be declared and defined separately, and so only WX_DEFINE_ARRAY_INT() +exists, without the matching "DECLARE" macro. The "DECLARE" macro declares a new container class containing the elements of -given type and is needed for all three types of container classes: lists, -arrays and objarrays. The "DEFINE" classes must be inserted in your program in -a place where the @e full declaration of container element class is in scope -(i.e. not just forward declaration), otherwise destructors of the container -elements will not be called! - -As array classes never delete the items they contain anyhow, there is no -WX_DEFINE_ARRAY() macro for them. - -Examples of usage of these macros may be found in wxList and wxArray -documentation. +given type and can be used in a header file and don't require the full +declaration of the contained type. The "DEFINE" macros must be used in a place +where the @e full declaration of container element class is in scope (i.e. not +just forward declaration). Finally, wxWidgets predefines several commonly used container classes. wxList -is defined for compatibility with previous versions as a list containing -wxObjects and wxStringList as a list of C-style strings (char *), both of these -classes are deprecated and should not be used in new programs. The following -array classes are defined: wxArrayInt, wxArrayLong, wxArrayPtrVoid and -wxArrayString. The first three store elements of corresponding types, but -wxArrayString is somewhat special: it is an optimized version of wxArray which -uses its knowledge about wxString reference counting schema. +itself is defined for compatibility with very old versions of wxWidgets as a +list containing wxObjects and wxStringList as a list of C-style strings +(`char *`). There are also a few predefined array classes including wxArrayInt, +wxArrayLong, wxArrayPtrVoid and wxArrayString, similar to `std::vector` +instantiations for `int`, `long`, `void*` and `wxString` respectively. -@section overview_container_std STL Build +@section overview_container_impls Different Implementations -To build wxWidgets with the standard containers you need to set -wxUSE_STD_CONTAINERS option to 1 in @c wx/msw/setup.h for wxMSW builds or -specify @c \--enable-std_containers option to configure (which is also -implicitly enabled by @c \--enable-stl option) in Unix builds. +Since wxWidgets 3.3.0, all legacy container classes are implemented in terms of +the standard library classes. These implementations are mostly, but not +completely, compatible with the implementation provided by wxWidgets itself +which was used by default in the previous versions. -The standard container build is mostly, but not quite, compatible with the -default one. Here are the most important differences: - - wxList::compatibility_iterator must be used instead of wxList::Node* when - iterating over the list contents. The compatibility_iterator class has the - same semantics as a Node pointer but it is an object and not a pointer, so - you need to write +If the existing code doesn't compile with the implementation based on the +standard containers, it's possible to rebuild the library to use the legacy +implementation of them by setting wxUSE_STD_CONTAINERS option to 0. This is +done by: + +- Either manually editing `wx/msw/setup.h` file to change the option of this + value there for wxMSW. +- Or using `--disable-std_containers` option when calling configure when + building wxWidgets under Unix-like systems. +- Or using `-DwxUSE_STD_CONTAINERS=OFF` when using CMake build system. + + +However a better approach is to update the legacy code to work with the new +container classes implementation. In most cases this can be done in such a way +that they still continue to work with the legacy implementation as well, thus +allowing the application to compile with the default configurations of both +wxWidgets 3.3 and 3.2 and even earlier versions. + +Here are some modifications that may need to be done in order to make the +existing compatible with the default build of wxWidgets 3.3: + + - `wxList::compatibility_iterator` must be used instead of `wxList::Node*` when + iterating over the list contents. The `compatibility_iterator` class has the + same semantics as a `Node` pointer but it is an object and not a pointer, so + the old code doing + @code + for ( wxWindowList::Node *n = list.GetFirst(); n; n = n->GetNext() ) { + // ... do something with *n ... + } + @endcode + can be mechanically rewritten as @code for ( wxWindowList::compatibility_iterator it = list.GetFirst(); it; - it = it->GetNext() ) - ... + it = it->GetNext() ) { + // ... do something with *it ... + } @endcode - instead of the old + Of course, if compatibility with the previous wxWidgets versions is not + important, an even better and simpler way to rewrite it is @code - for ( wxWindowList::Node *n = list.GetFirst(); n; n = n->GetNext() ) - ... + for ( const auto& elem: list ) { + // ... do something with elem ... + } @endcode - wxSortedArrayString and wxArrayString are separate classes now and the former doesn't derive from the latter. If you need to convert a sorted array to a normal one, you must copy all the elements. Alternatively, you may avoid the use of wxSortedArrayString by using a normal array and calling its - Sort() method when needed. - - WX_DEFINE_ARRAY_INT(bool) cannot be used because of the differences in - std::vector specialization compared with the generic std::vector<> - class. Please either use std::vector directly or use an integer array + wxArrayString::Sort() method when needed. + - `WX_DEFINE_ARRAY_INT(bool)` cannot be used because of the differences in + `std::vector` specialization compared with the generic std::vector<> + class. Please either use `std::vector` directly or use wxArrayInt instead. */ diff --git a/interface/wx/arrstr.h b/interface/wx/arrstr.h index a817eda4cf..19802cdcaf 100644 --- a/interface/wx/arrstr.h +++ b/interface/wx/arrstr.h @@ -10,7 +10,8 @@ wxArrayString is a legacy class similar to std::vector. - This class shouldn't normally be used in the new code, but is still needed + As all the other legacy @ref overview_container "container classes", + this class shouldn't normally be used in the new code, but is still needed when passing multiple items to various functions in wxWidgets API, notably the constructors of various GUI control classes. Usually, even in this case it doesn't need to be used explicitly, as wxArrayString will be implicitly @@ -123,8 +124,10 @@ public: /** Constructs the container with the contents of the vector @a vec. - When using @ref overview_container_std, this constructor is more - efficient than the overload taking const reference to the vector. + In the default build, in which wxArrayString is implemented using + `std::vector<>` internally, this constructor is more efficient than the + overload taking const reference to the vector, as it reuses the + existing vector data instead of copying it. Otherwise it is identical to the other overload, see its documentation for more details. @@ -158,17 +161,18 @@ public: /** 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. + In the default build configuration, this function returns a const + reference to this object itself, without making a copy. But when using + the legacy implementation of wxArrayString not based on `std::vector`, + 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. + works in all build variants as long as you don't need to modify the + returned vector and doesn't impose any extra overhead. @since 3.3.0 */ diff --git a/interface/wx/dynarray.h b/interface/wx/dynarray.h index 384d1b9614..e3cb71ffb0 100644 --- a/interface/wx/dynarray.h +++ b/interface/wx/dynarray.h @@ -9,6 +9,9 @@ The legacy dynamic array class, existing for compatibility only and @e NOT to be used in the new code. + @note Please see @ref overview_container for more information about legacy + container classes in wxWidgets. + This section describes the so called @e "dynamic arrays". This is a C array-like type safe data structure i.e. the member access time is constant (and not linear according to the number of container elements as for linked diff --git a/interface/wx/hashmap.h b/interface/wx/hashmap.h index f79a920959..0e88577aa3 100644 --- a/interface/wx/hashmap.h +++ b/interface/wx/hashmap.h @@ -6,12 +6,14 @@ ///////////////////////////////////////////////////////////////////////////// /** - @class wxHashMap + wxHashMap is a legacy hash table container similar to std::unordered_map. - This is a simple, type-safe, and reasonably efficient hash map class, - whose interface is a subset of the interface of STL containers. - In particular, the interface is modelled after std::map, and the various, - non-standard, std::hash_map (http://www.cppreference.com/wiki/stl/map/start). + @note As all the other legacy @ref overview_container "container classes", + this class shouldn't be used in the new code. + + Please see https://en.cppreference.com/w/cpp/container/unordered_map for + the full description of this class API: in the default build, this class is + a thin wrapper inheriting from the standard class. Example: @code diff --git a/interface/wx/hashset.h b/interface/wx/hashset.h index ca83ac75d2..3f45f8dbcd 100644 --- a/interface/wx/hashset.h +++ b/interface/wx/hashset.h @@ -6,13 +6,14 @@ ///////////////////////////////////////////////////////////////////////////// /** - @class wxHashSet + wxHashSet is a legacy hash set container similar to std::unordered_set. - This is a simple, type-safe, and reasonably efficient hash set class, - whose interface is a subset of the interface of STL containers. + @note As all the other legacy @ref overview_container "container classes", + this class shouldn't be used in the new code. - The interface is similar to std::tr1::hash_set or std::set classes but - notice that, unlike std::set, the contents of a hash set is not sorted. + Please see https://en.cppreference.com/w/cpp/container/unordered_set for + the full description of this class API: in the default build, this class is + a thin wrapper inheriting from the standard class. Example: @code diff --git a/interface/wx/list.h b/interface/wx/list.h index 1215e031b6..4c25e86c9d 100644 --- a/interface/wx/list.h +++ b/interface/wx/list.h @@ -6,17 +6,20 @@ ///////////////////////////////////////////////////////////////////////////// /** - The wxList class provides linked list functionality. + wxList is a legacy class similar to std::list. - This class has been rewritten to be type safe and to provide the full API of - the STL std::list container and should be used like it if you use it at - all, which is not recommended in the new code. + @note As all the other legacy @ref overview_container "container classes", + this class shouldn't be used in the new code. - The exception is that wxList actually stores pointers and therefore its - iterators return pointers and not references to the actual objects in the list - (see example below) and @e value_type is defined as @e T*. - wxList destroys an object after removing it only if wxList::DeleteContents - has been called. + This class is similar to the other container classes in that it provides + all the usual functions of its standard library counterpart, `std::list`. + However, unlike the other classes, this class always stores pointers to the + objects and not the objects themselves, i.e. its @e value_type is defined + as @e T*. + + Moreover, wxList only destroys an object after removing it if + wxList::DeleteContents has been called, i.e. it does _not_ manage its + items memory by default. wxList is not a real template and it requires that you declare and define each wxList class in your program. This is done with @e WX_DECLARE_LIST @@ -24,16 +27,12 @@ provide a proper template class providing both the STL @c std::list and the old wxList API in the future. - Please refer to the STL @c std::list documentation (see http://www.cppreference.com/wiki/stl/list/start) + Please refer to the STL @c std::list documentation (see https://en.cppreference.com/w/cpp/container/list) for further information on how to use the class. Below we documented both the supported STL and the legacy API that originated from the old wxList class and which can still be used alternatively for the same class. - Note that if you use @ref overview_container_std of wxWidgets, - then wxList will actually derive from @c std::list and just add a legacy - compatibility layer for the old wxList class. - @code // this part might be in a header or source (.cpp) file class MyListElement From 0964b93ccd2d44858b7b6bd9885f1123261d96b2 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 10 Apr 2023 20:40:00 +0100 Subject: [PATCH 10/10] Add a CI build using wx implementation of container classes As long as we support building with wxUSE_STD_CONTAINERS==0, we need to test that this build still works. --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4d9ea3ec90..6ef6644353 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -104,6 +104,10 @@ jobs: compiler: clang++-10 configure_flags: --disable-sys-libs use_xvfb: true + - name: Ubuntu 22.04 wxGTK with wx containers + runner: ubuntu-22.04 + configure_flags: --enable-compat30 --disable-std_containers + use_xvfb: true - name: Ubuntu 22.04 wxGTK with ASAN runner: ubuntu-22.04 configure_flags: --disable-compat32 --disable-sys-libs