mirror of
https://github.com/boostorg/unordered.git
synced 2025-07-29 19:07:15 +02:00
Unordered: Documentation update.
[SVN r74962]
This commit is contained in:
@ -134,16 +134,23 @@ First official release.
|
||||
* Fix a bug when inserting into an `unordered_map` or `unordered_set` using
|
||||
iterators which returns `value_type` by copy.
|
||||
|
||||
[h2 Boost 1.48.0]
|
||||
[h2 Boost 1.48.0 - Major update]
|
||||
|
||||
This is major change which has been converted to use Boost.Move's move
|
||||
emulation, and be more compliant with the C++11 standard. This has resulted
|
||||
in some breaking changes:
|
||||
emulation, and be more compliant with the C++11 standard. See the
|
||||
[link unordered.compliance compliance section] for details.
|
||||
|
||||
The container now meets C++11's complexity requirements, but to do so
|
||||
uses a little more memory. This means that `quick_erase` and
|
||||
`erase_return_void` are no longer required, they'll be removed in a
|
||||
future version.
|
||||
|
||||
C++11 support has resulted in some breaking changes:
|
||||
|
||||
* Equality comparison has been changed to the C++11 specification.
|
||||
In a container with equivalent keys, elements in a group with equal
|
||||
keys used to have to be in the same order to be considered equal,
|
||||
now they can be a permutation of each other. To keep the old
|
||||
now they can be a permutation of each other. To use the old
|
||||
behavior define the macro `BOOST_UNORDERED_DEPRECATED_EQUALITY`.
|
||||
|
||||
* The behaviour of swap is different when the two containers to be
|
||||
|
@ -4,59 +4,80 @@
|
||||
|
||||
[section:compliance C++11 Compliance]
|
||||
|
||||
[section:allocator_compliance Use of allocators]
|
||||
|
||||
C++11 introduced a new, mostly backwards compatible, allocator system.
|
||||
This uses a traits class, `allocator_traits` to handle the allocator
|
||||
adding extra functionality, and making some methods and types optional.
|
||||
At the time of writing there isn't a stable release of a standard library
|
||||
with `allocator_traits` (libc++ has `allocator_traits` but it hasn't been
|
||||
released yet) so a partial implementation is always used.
|
||||
|
||||
A full implementation of `allocator_traits` requires sophisticated
|
||||
member function detection which requires support for SFINAE expressions,
|
||||
or something close. This is available on GCC from version 4.4, Clang and
|
||||
Visual C++ 2008 (with a little hacking) or later.
|
||||
|
||||
On these compilers, the `construct`, `destroy` and `max_size` member functions
|
||||
are optional, as per C++11. On other compilers they are still required.
|
||||
|
||||
`propagate_on_container_copy_assignment`,
|
||||
`propagate_on_container_move_assignment` and
|
||||
`propagate_on_container_swap` are supported on most compilers
|
||||
(/TODO/: which ones don't support them?).
|
||||
`select_on_container_copy_construction` is also supported, but on
|
||||
compilers without full member function detection it must have exactly
|
||||
the right function signature, and can't be declared in a base class
|
||||
in order for it to be detected.
|
||||
|
||||
The use of the allocator's construct and destruct methods might be a bit
|
||||
surprising.
|
||||
Nodes are constructed and destructed using the allocator, but the objects
|
||||
contained in the node are stored in aligned space within the node
|
||||
and constructed and destructed by calling the constructor and destructor
|
||||
directly. So `construct` and `destroy` are called for the node, but not for
|
||||
the object.
|
||||
|
||||
`pointer_traits` aren't used. Instead, pointer types are obtained from
|
||||
rebound allocators.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:move Move emulation]
|
||||
|
||||
Move emulation is implemented using Boost.Move. If rvalue references are
|
||||
available it will use them, but if not it uses a close, but imperfect emulation
|
||||
and to get the advantage of using movable container elements, you'll need to
|
||||
use Boost.Move.
|
||||
Support for move semantics is implemented using Boost.Move. If rvalue
|
||||
references are available it will use them, but if not it uses a close,
|
||||
but imperfect emulation. On such compilers you'll need to use Boost.Move
|
||||
to take advantage of using movable container elements, also note that:
|
||||
|
||||
* Non-copyable objects can be stored in the containers, but without support
|
||||
for rvalue references the container will not be movable.
|
||||
* The number of arguments used in `emplace` is limited to /TODO/.
|
||||
* Argument forwarding is not perfect.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:allocator_compliance Use of allocators]
|
||||
|
||||
C++11 introduced a new allocator system. It's backwards compatible due to
|
||||
the lax requirements for allocators in the old standard, but might need
|
||||
some changes for allocators which worked with the old versions of the
|
||||
unordered containers.
|
||||
It uses a traits class, `allocator_traits` to handle the allocator
|
||||
adding extra functionality, and making some methods and types optional.
|
||||
During development a stable release of
|
||||
`allocator_traits` wasn't available so an internal partial implementation
|
||||
is always used in this version. Hopefully a future version will use the
|
||||
standard implementation where available.
|
||||
|
||||
The member functions `construct`, `destroy` and `max_size` are now
|
||||
optional, if they're not available a fallback is used.
|
||||
A full implementation of `allocator_traits` requires sophisticated
|
||||
member function detection so that the fallback is used whenever the
|
||||
member function call is not well formed.
|
||||
This requires support for SFINAE expressions, which are available on
|
||||
GCC from version 4.4 and Clang. They aren't supported by
|
||||
Visual C++ 2008/2010, but with a bit of hacking it's possible to support
|
||||
certain use cases.
|
||||
|
||||
On other compilers, there's just a test to see if the allocator has
|
||||
a member, but no check that it can be called. So rather than using a
|
||||
fallback there will just be a compile error.
|
||||
|
||||
`propagate_on_container_copy_assignment`,
|
||||
`propagate_on_container_move_assignment`,
|
||||
`propagate_on_container_swap` and
|
||||
`select_on_container_copy_construction` are also supported.
|
||||
Due to imperfect move emulation, some assignments might check
|
||||
`propagate_on_container_copy_assignment` on some compilers and
|
||||
`propagate_on_container_move_assignment` on others.
|
||||
|
||||
The use of the allocator's construct and destruct methods might be a bit
|
||||
surprising.
|
||||
Nodes are constructed and destructed using the allocator, but the elements
|
||||
are stored in aligned space within the node and constructed and destructed
|
||||
by calling the constructor and destructor directly.
|
||||
|
||||
In C++11 the allocator's construct function has the signature:
|
||||
|
||||
template <class U, class... Args>
|
||||
void construct(U* p, Args&&... args);
|
||||
|
||||
which supports calling `construct` for the contained object, but
|
||||
most existing allocators don't support this. If member function detection
|
||||
was good enough then with old allocators it would fall back to calling
|
||||
the element's constructor directly but in general, detection isn't good
|
||||
enough to do this which is why Boost.Unordered just calls the constructor
|
||||
directly every time. In most cases this will work okay.
|
||||
|
||||
`pointer_traits` aren't used. Instead, pointer types are obtained from
|
||||
rebound allocators, this can cause problems if the allocator can't be
|
||||
used with incomplete types. If `const_pointer` is not defined in the
|
||||
allocator, `boost::pointer_to_other<pointer, const value_type>::type`
|
||||
is used to obtain a const pointer.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:pairs Pairs]
|
||||
|
||||
Since the containers use `std::pair` they're limited to the version
|
||||
@ -74,22 +95,19 @@ namespace. So for example, the following will work:
|
||||
Older drafts of the standard also supported variadic constructors
|
||||
for `std::pair`, where the first argument would be used for the
|
||||
first part of the pair, and the remaining for the second part.
|
||||
For the same example:
|
||||
|
||||
x.emplace("key", 1, 2);
|
||||
|
||||
This is emulated in Boost.Unordered, but will be deprecated soon.
|
||||
While it is a lot more compact, it lead to ambiguities so it was
|
||||
removed.
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:swap Swapping]
|
||||
[section:misc Miscellaneous]
|
||||
|
||||
When swapping, `Pred` and `Hash` are not currently swapped by calling
|
||||
`swap`, their copy constructors are used. As a consequence when swapping
|
||||
an exception may be throw from their copy constructor.
|
||||
|
||||
Variadic constructor arguments for `emplace` are only used when both
|
||||
rvalue references and variadic template parameters are available.
|
||||
Otherwise `emplace` can only take up to 10 constructors arguments.
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
||||
|
19
doc/ref.php
19
doc/ref.php
@ -116,16 +116,28 @@ EOL;
|
||||
</typedef>
|
||||
<typedef name="pointer">
|
||||
<type>typename allocator_type::pointer</type>
|
||||
<description>
|
||||
<para>
|
||||
<code>value_type*</code> if
|
||||
<code>allocator_type::pointer</code> is not defined.
|
||||
</para>
|
||||
</description>
|
||||
</typedef>
|
||||
<typedef name="const_pointer">
|
||||
<type>typename allocator_type::const_pointer</type>
|
||||
<description>
|
||||
<para>
|
||||
<code>boost::pointer_to_other<pointer, value_type>::type</code>
|
||||
if <code>allocator_type::const_pointer</code> is not defined.
|
||||
</para>
|
||||
</description>
|
||||
</typedef>
|
||||
<typedef name="reference">
|
||||
<type>typename allocator_type::reference</type>
|
||||
<type>value_type&</type>
|
||||
<purpose><simpara>lvalue of <type>value_type</type>.</simpara></purpose>
|
||||
</typedef>
|
||||
<typedef name="const_reference">
|
||||
<type>typename allocator_type::const_reference</type>
|
||||
<type>value_type const&</type>
|
||||
<purpose><simpara>const lvalue of <type>value_type</type>.</simpara></purpose>
|
||||
</typedef>
|
||||
<typedef name="size_type">
|
||||
@ -320,7 +332,8 @@ EOL;
|
||||
<notes>
|
||||
<para>
|
||||
On compilers without rvalue references, this is emulated using
|
||||
Boost.Move.
|
||||
Boost.Move. Note that on some compilers the copy assignment
|
||||
operator may be used in some circumstances.
|
||||
</para>
|
||||
</notes>
|
||||
<requires>
|
||||
|
76
doc/ref.xml
76
doc/ref.xml
@ -61,16 +61,28 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
</typedef>
|
||||
<typedef name="pointer">
|
||||
<type>typename allocator_type::pointer</type>
|
||||
<description>
|
||||
<para>
|
||||
<code>value_type*</code> if
|
||||
<code>allocator_type::pointer</code> is not defined.
|
||||
</para>
|
||||
</description>
|
||||
</typedef>
|
||||
<typedef name="const_pointer">
|
||||
<type>typename allocator_type::const_pointer</type>
|
||||
<description>
|
||||
<para>
|
||||
<code>boost::pointer_to_other<pointer, value_type>::type</code>
|
||||
if <code>allocator_type::const_pointer</code> is not defined.
|
||||
</para>
|
||||
</description>
|
||||
</typedef>
|
||||
<typedef name="reference">
|
||||
<type>typename allocator_type::reference</type>
|
||||
<type>value_type&</type>
|
||||
<purpose><simpara>lvalue of <type>value_type</type>.</simpara></purpose>
|
||||
</typedef>
|
||||
<typedef name="const_reference">
|
||||
<type>typename allocator_type::const_reference</type>
|
||||
<type>value_type const&</type>
|
||||
<purpose><simpara>const lvalue of <type>value_type</type>.</simpara></purpose>
|
||||
</typedef>
|
||||
<typedef name="size_type">
|
||||
@ -265,7 +277,8 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<notes>
|
||||
<para>
|
||||
On compilers without rvalue references, this is emulated using
|
||||
Boost.Move.
|
||||
Boost.Move. Note that on some compilers the copy assignment
|
||||
operator may be used in some circumstances.
|
||||
</para>
|
||||
</notes>
|
||||
<requires>
|
||||
@ -1001,16 +1014,28 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
</typedef>
|
||||
<typedef name="pointer">
|
||||
<type>typename allocator_type::pointer</type>
|
||||
<description>
|
||||
<para>
|
||||
<code>value_type*</code> if
|
||||
<code>allocator_type::pointer</code> is not defined.
|
||||
</para>
|
||||
</description>
|
||||
</typedef>
|
||||
<typedef name="const_pointer">
|
||||
<type>typename allocator_type::const_pointer</type>
|
||||
<description>
|
||||
<para>
|
||||
<code>boost::pointer_to_other<pointer, value_type>::type</code>
|
||||
if <code>allocator_type::const_pointer</code> is not defined.
|
||||
</para>
|
||||
</description>
|
||||
</typedef>
|
||||
<typedef name="reference">
|
||||
<type>typename allocator_type::reference</type>
|
||||
<type>value_type&</type>
|
||||
<purpose><simpara>lvalue of <type>value_type</type>.</simpara></purpose>
|
||||
</typedef>
|
||||
<typedef name="const_reference">
|
||||
<type>typename allocator_type::const_reference</type>
|
||||
<type>value_type const&</type>
|
||||
<purpose><simpara>const lvalue of <type>value_type</type>.</simpara></purpose>
|
||||
</typedef>
|
||||
<typedef name="size_type">
|
||||
@ -1205,7 +1230,8 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<notes>
|
||||
<para>
|
||||
On compilers without rvalue references, this is emulated using
|
||||
Boost.Move.
|
||||
Boost.Move. Note that on some compilers the copy assignment
|
||||
operator may be used in some circumstances.
|
||||
</para>
|
||||
</notes>
|
||||
<requires>
|
||||
@ -1951,16 +1977,28 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
</typedef>
|
||||
<typedef name="pointer">
|
||||
<type>typename allocator_type::pointer</type>
|
||||
<description>
|
||||
<para>
|
||||
<code>value_type*</code> if
|
||||
<code>allocator_type::pointer</code> is not defined.
|
||||
</para>
|
||||
</description>
|
||||
</typedef>
|
||||
<typedef name="const_pointer">
|
||||
<type>typename allocator_type::const_pointer</type>
|
||||
<description>
|
||||
<para>
|
||||
<code>boost::pointer_to_other<pointer, value_type>::type</code>
|
||||
if <code>allocator_type::const_pointer</code> is not defined.
|
||||
</para>
|
||||
</description>
|
||||
</typedef>
|
||||
<typedef name="reference">
|
||||
<type>typename allocator_type::reference</type>
|
||||
<type>value_type&</type>
|
||||
<purpose><simpara>lvalue of <type>value_type</type>.</simpara></purpose>
|
||||
</typedef>
|
||||
<typedef name="const_reference">
|
||||
<type>typename allocator_type::const_reference</type>
|
||||
<type>value_type const&</type>
|
||||
<purpose><simpara>const lvalue of <type>value_type</type>.</simpara></purpose>
|
||||
</typedef>
|
||||
<typedef name="size_type">
|
||||
@ -2155,7 +2193,8 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<notes>
|
||||
<para>
|
||||
On compilers without rvalue references, this is emulated using
|
||||
Boost.Move.
|
||||
Boost.Move. Note that on some compilers the copy assignment
|
||||
operator may be used in some circumstances.
|
||||
</para>
|
||||
</notes>
|
||||
<requires>
|
||||
@ -2936,16 +2975,28 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
</typedef>
|
||||
<typedef name="pointer">
|
||||
<type>typename allocator_type::pointer</type>
|
||||
<description>
|
||||
<para>
|
||||
<code>value_type*</code> if
|
||||
<code>allocator_type::pointer</code> is not defined.
|
||||
</para>
|
||||
</description>
|
||||
</typedef>
|
||||
<typedef name="const_pointer">
|
||||
<type>typename allocator_type::const_pointer</type>
|
||||
<description>
|
||||
<para>
|
||||
<code>boost::pointer_to_other<pointer, value_type>::type</code>
|
||||
if <code>allocator_type::const_pointer</code> is not defined.
|
||||
</para>
|
||||
</description>
|
||||
</typedef>
|
||||
<typedef name="reference">
|
||||
<type>typename allocator_type::reference</type>
|
||||
<type>value_type&</type>
|
||||
<purpose><simpara>lvalue of <type>value_type</type>.</simpara></purpose>
|
||||
</typedef>
|
||||
<typedef name="const_reference">
|
||||
<type>typename allocator_type::const_reference</type>
|
||||
<type>value_type const&</type>
|
||||
<purpose><simpara>const lvalue of <type>value_type</type>.</simpara></purpose>
|
||||
</typedef>
|
||||
<typedef name="size_type">
|
||||
@ -3140,7 +3191,8 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
<notes>
|
||||
<para>
|
||||
On compilers without rvalue references, this is emulated using
|
||||
Boost.Move.
|
||||
Boost.Move. Note that on some compilers the copy assignment
|
||||
operator may be used in some circumstances.
|
||||
</para>
|
||||
</notes>
|
||||
<requires>
|
||||
|
Reference in New Issue
Block a user