Merge branch 'use-std-cont-1'
Set wxUSE_STD_CONTAINERS=1 by default. See #23439.
This commit is contained in:
commit
fb17a5ac38
24 changed files with 225 additions and 179 deletions
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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<T> and wxArray<T> 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<T> or wxArray<T>, you can work with
|
||||
them as if they were just `std::list<T*>` or `std::vector<T>`. For example,
|
||||
wxWidgets::GetChildren() is documented as returning a `wxWindowList`, which
|
||||
inherits from `std::list<wxWindow*>` 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<T>, wxStack<T> or wxDList which can be used exactly
|
||||
like the std::vector<T>, std::stack<T> and std::list<T*>, 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<T> and std::list<T> if possible and wxVector<T> or wxDList<T> if
|
||||
it isn't and only use legacy wxWidgets containers such as wxArray<T> and
|
||||
wxList<T> 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<wxString>` 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<T>::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<T> and wxArray<T>
|
||||
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<bool> specialization compared with the generic std::vector<>
|
||||
class. Please either use std::vector<bool> 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<bool>` specialization compared with the generic std::vector<>
|
||||
class. Please either use `std::vector<bool>` directly or use wxArrayInt
|
||||
instead.
|
||||
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue