From 4e249125ebc32f3169dbfb424f9669392610210a Mon Sep 17 00:00:00 2001 From: Christian Mazakas Date: Tue, 18 Jan 2022 15:35:34 -0800 Subject: [PATCH] Update compliance section to AsciiDoc --- doc/unordered/compliance.adoc | 114 ++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/doc/unordered/compliance.adoc b/doc/unordered/compliance.adoc index 985e0c59..411a1ecf 100644 --- a/doc/unordered/compliance.adoc +++ b/doc/unordered/compliance.adoc @@ -1,2 +1,116 @@ [#compliance] = Standard Compliance + +:idprefix: compliance_ + +:cpp: C++ + +The intent of Boost.Unordered is to implement a close (but imperfect) +implementation of the {cpp}17 standard, that will work with {cpp}98 upwards. +The wide compatibility does mean some comprimises have to be made. +With a compiler and library that fully support {cpp}11, the differences should +be minor. + +== Move emulation + +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: + +* Non-copyable objects can be stored in the containers. + They can be constructed in place using `emplace`, or if they support + Boost.Move, moved into place. +* The containers themselves are not movable. +* Argument forwarding is not perfect. + +== Use of allocators + +{cpp}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. + +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. + +== Construction/Destruction using allocators + +The following support is required for full use of {cpp}11 style +construction/destruction: + +* Variadic templates. +* Piecewise construction of `std::pair`. +* Either `std::allocator_traits` or expression SFINAE. + +This is detected using Boost.Config. The macro +`BOOST_UNORDERED_CXX11_CONSTRUCTION` will be set to 1 if it is found, or 0 +otherwise. + +When this is the case `allocator_traits::construct` and +`allocator_traits::destroy` will always be used, apart from when piecewise +constructing a `std::pair` using `boost::tuple` (see <>), but that should be easily avoided. + +When support is not available `allocator_traits::construct` and +`allocator_traits::destroy` are never called. + +== Pointer Traits + +`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::type` +is used to obtain a const pointer. + +== Pairs + +Since the containers use `std::pair` they're limited to the version +from the current standard library. But since {cpp}11 ``std::pair``'s +`piecewise_construct` based constructor is very useful, `emplace` +emulates it with a `piecewise_construct` in the `boost::unordered` +namespace. So for example, the following will work: + +[source,c++] +---- +boost::unordered_multimap 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. + +== 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 thrown 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.