Unordered: Documentation update.

[SVN r74962]
This commit is contained in:
Daniel James
2011-10-16 10:31:25 +00:00
parent 087962c16e
commit d2a6ad8c72
4 changed files with 161 additions and 71 deletions

View File

@ -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

View File

@ -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]

View File

@ -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&lt;pointer, value_type&gt;::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&amp;</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&amp;</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>

View File

@ -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&lt;pointer, value_type&gt;::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&amp;</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&amp;</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&lt;pointer, value_type&gt;::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&amp;</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&amp;</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&lt;pointer, value_type&gt;::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&amp;</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&amp;</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&lt;pointer, value_type&gt;::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&amp;</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&amp;</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>