...one of the most highly
regarded and expertly designed C++ library projects in the
world. — Herb Sutter and Andrei
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:
emplace, or if they support Boost.Move, moved into place.
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,
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
max_size are now optional, if they're not
available a fallback is used. A full implementation of
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
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.
are also supported. Due to imperfect move emulation, some assignments might
on some compilers and
The following support is required for full use of C++11 style construction/destruction:
std::allocator_traitsor expression SFINAE.
This is detected using Boost.Config. The macro
will be set to 1 if it is found, or 0 otherwise.
When this is the case
allocator_traits::destroy will always be used, apart from
when piecewise constructing a
boost::tuple (see below),
but that should be easily avoided.
When support is not available
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
they're limited to the version from the current standard library. But since
based constructor is very useful,
emulates it with a
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
where the first argument would be used for the first part of the pair, and
the remaining for the second part.
Hash are not currently swapped
swap, their copy
constructors are used. As a consequence when swapping an exception may be
thrown from their copy constructor.
Variadic constructor arguments for
are only used when both rvalue references and variadic template parameters
are available. Otherwise
can only take up to 10 constructors arguments.