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.
This commit is contained in:
parent
3335be1362
commit
89e4f51f62
7 changed files with 137 additions and 113 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.
|
||||
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@
|
|||
|
||||
wxArrayString is a legacy class similar to std::vector<wxString>.
|
||||
|
||||
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<wxString>& 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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -6,17 +6,20 @@
|
|||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
The wxList<T> class provides linked list functionality.
|
||||
wxList<T> is a legacy class similar to std::list<T*>.
|
||||
|
||||
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<T> 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<T> destroys an object after removing it only if wxList<T>::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<T> only destroys an object after removing it if
|
||||
wxList<T>::DeleteContents has been called, i.e. it does _not_ manage its
|
||||
items memory by default.
|
||||
|
||||
wxList<T> is not a real template and it requires that you declare and define
|
||||
each wxList<T> 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<T> 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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue