Unordered: More info on C++11 compliance.

[SVN r74134]
This commit is contained in:
Daniel James
2011-08-29 15:20:27 +00:00
parent f64b5ba3f8
commit 568fd1758d

View File

@ -4,25 +4,42 @@
[section:compliance C++11 Compliance] [section:compliance C++11 Compliance]
/TODO/: Look into C++11's `std::pair`.
[section:allocator_compliance Use of allocators] [section:allocator_compliance Use of allocators]
* Objects are not constructed using the allocator. The node containing them C++11 introduced a new, mostly backwards compatible, allocator system.
is constructed using the allocator's `construct` function, but then the This uses a traits class, `allocator_traits` to handle the allocator
object is constructed in a buffer in that node by calling the constructor adding extra functionality, and making some methods and types optional.
directly. At the time of writing there isn't a stable release of a standard library
* Similarly the object is destructed by calling its destructor directly, and with `allocator_traits` (libc++ has `allocator_traits` but it hasn't been
then the allocator's `destroy` method is used to destruct the node. released yet) so a partial implementation is always used.
* For most compilers `select_on_container_copy` is only detected for an
exact signature match in the allocator itself - not in a base. There is full A full implementation of `allocator_traits` requires sophisticated
detection for g++ 4.4 or laster, Visual C++ 2008 or later, Clang and maybe member function detection which requires support for SFINAE expressions,
other compilers which support SFINAE for expressions. or something close. This is available on GCC from version 4.4, Clang and
* `pointer_traits` aren't used. Instead, pointer types are obtained from Visual C++ 2008 (with a little hacking) or later.
rebound allocators.
* /TODO/: Any other defficiences of `allocator_traits` emulation. On these compilers, the `construct`, `destroy` and `max_size` member functions
* Pointers of base types are used to store the location of a derived type. are optional, as per C++11. On other compilers they are still required.
(/TODO/: I'm not sure if that isn't compliant).
`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] [endsect]
@ -35,19 +52,43 @@ use Boost.Move.
* Non-copyable objects can be stored in the containers, but without support * Non-copyable objects can be stored in the containers, but without support
for rvalue references the container will not be movable. for rvalue references the container will not be movable.
* The number of arguments used in emplace is limited to /TODO/. * The number of arguments used in `emplace` is limited to /TODO/.
* Argument forwarding is not perfect. * Argument forwarding is not perfect.
* /TODO/: Constructor call for pairs.
[endsect] [endsect]
[section:other Other] [section:pairs Pairs]
* When swapping, `Pred` and `Hash` are not currently swapped by calling Since the containers use `std::pair` they're limited to the version
`swap`, their copy constructors are used. from the current standard library. But since C++11 `std::pair`'s
* As a consequence when swapping an exception may be throw from their `piecewise_construct` based constructor is very useful, `emplace`
copy constructor. emulates it with a `piecewise_construct` in the `boost::unordered`
namespace. So for example, the following will work:
boost::unordered_multimap<std::string, std::complex> x;
x.emplace(
boost::unordered::piecewise_construct,
boost::make_tuple("key"), boost::make_tuple(1, 2));
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]
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.
[endsect] [endsect]