Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

Standard Compliance

Move emulation
Use of allocators
Construction/Destruction using allocators
Pointer Traits
Pairs
Miscellaneous

The intent of Boost.Unordered is to implement a close (but imperfect) implementation of the C++17 standard, that will work with C++98 upwards. The wide compatibility does mean some comprimises have to be made. With a compiler and library that fully support C++11, the differences should be minor.

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.

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.

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 following support is required for full use of C++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 below), but that should be easily avoided.

When support is not available allocator_traits::construct and allocator_traits::destroy are never called.

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.

Since the containers use std::pair they're limited to the version from the current standard library. But since C++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:

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.

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.


PrevUpHomeNext