...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
Boost.MultiIndex utilizes some C++11 capabilities but is also equipped to work reasonably well in decent C++03-compliant environments. We list some of the possible limitations along with suitable workarounds when available.
Boost.MultiIndex uses Boost.Move
to support compilers without rvalue references. In such scenarios, taking
advantage of multi_index_container<Value>
capabilities for
increased efficiency in insertion and handling of moveable-only elements will
require that Value
be suitably instrumented.
In pre-C++11 compilers or defective environments without proper
allocator
awareness machinery (basically, std::allocator_traits
),
Boost.MultiIndex behaves as if
std::allocator_traits<allocator_type>::propagate_on_container_*::value
were false
for all allocators.
In compilers without variadic template support, Boost.MultiIndex emplace
functions emulate this missing functionality by accepting up to
BOOST_MULTI_INDEX_LIMIT_VARTEMPL_ARGS
construction arguments that are internally forwarded with
Boost.Move:
only constant lvalue references and rvalues are permitted as construction arguments
in such case.
BOOST_MULTI_INDEX_LIMIT_VARTEMPL_ARGS
, which by default is 5, can
be globally defined by the user to a different value.
No transparent emulation of this functionality can be provided in the absence of
std::initializer_list
: consider
Boost.Assign as a
possible replacement.
Everywhere where std::tuple
s are used in the library interface,
boost::tuple
s can be resorted to in their place. The converse, however,
is not true.
The types generated on the instantiations of multi_index_container
s
typically produce very long symbol names, sometimes beyond the internal limits
of some compilers. There are several techniques to shorten generated symbol
names: these techniques have also the beneficial side effect that resulting error
messages are more readable.
The class templates indexed_by
,
tag
and
composite_key
accept a variable number of arguments whose maximum number is limited by
internal macros. Even non-used arguments contribute to the final types,
so manually adjusting the corresponding macros can result in a modest reduction
of symbol names.
class template | limiting macro | default value |
---|---|---|
indexed_by |
BOOST_MULTI_INDEX_LIMIT_INDEXED_BY_SIZE |
20 |
tag |
BOOST_MULTI_INDEX_LIMIT_TAG_SIZE |
20 |
composite_key |
BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE |
10 |
Consider a typical instantiation of multi_index_container
:
typedef multi_index_container< employee, indexed_by< ordered_unique<identity<employee> >, ordered_non_unique<member<employee,std::string,&employee::name> >, ordered_unique<member<employee,int,&employee::ssnumber> > > > employee_set;
Then, for instance, the type employee_set::nth_index<0>::type
resolves to the following in GCC:
boost::multi_index::detail::ordered_index< boost::multi_index::identity<employee>, std::less<employee>, boost::multi_index::detail::nth_layer< 1, employee, boost::multi_index::indexed_by< boost::multi_index::ordered_unique< boost::multi_index::identity<employee>, mpl_::na, mpl_::na >, boost::multi_index::ordered_non_unique< boost::multi_index::member<employee, std::string, &employee::name>, mpl_::na, mpl_::na >, boost::multi_index::ordered_unique< boost::multi_index::member<employee, int, &employee::ssnumber>, mpl_::na, mpl_::na >, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na >, std::allocator<employee> >, boost::mpl::vector0<mpl_::na>, boost::multi_index::detail::ordered_unique_tag >
It can be seen that a significant portion of the type name is contributed by
the indexed_by<...>
part, which is nothing but an expanded
version of the index specifier list provided in the definition of
employee_set
. We can prevent this very long name from appearing
in the final type by encapsulating it into another, shorter-named construct:
// reducing symbol names through type hiding // type hide the index specifier list within employee_set_indices struct employee_set_indices: indexed_by< ordered_unique<identity<employee> >, ordered_non_unique<member<employee,std::string,&employee::name> >, ordered_unique<member<employee,int,&employee::ssnumber> > > {}; typedef multi_index_container< employee, employee_set_indices > employee_set;
employee_set_indices
works as a conventional typedef
in all respects, save for a detail: its name does not explicitly
include the information contained in the indexed_by
instantiation.
Applying this technique, employee_set::nth_index<0>::type
now becomes:
boost::multi_index::detail::ordered_index< boost::multi_index::identity<employee>, std::less<employee>, boost::multi_index::detail::nth_layer< 1, employee, employee_set_indices, std::allocator<employee> >, boost::mpl::vector0<mpl_::na>, boost::multi_index::detail::ordered_unique_tag >
which is considerably shorter than the original, and also more
easily parsed by a human reader. Type hiding would not work if, instead of
making employee_set_indices
a derived struct
of
indexed_by<...>
, we had defined it as a typedef
:
typedef
s are syntactic aliases and usually get expanded
by the compiler before doing any further type handling.
Type hiding techniques can also be applied to composite_key
intantiations,
which often contribute a great deal to symbol name lengths.
Boost.MultiIndex support for legacy compilers is not actively kept, so if you happen to work with an old environment you might need to use a former version of the library. A table is provided of some legacy compilers along with the latest version of Boost.MultiIndex known to work for them (frequently with limitations as explained in the corresponding compiler specifics section.) If you successfully try one of those with newer versions of Boost.MultiIndex than stated here, please report back so that the information can be updated.
Compiler | Latest known compatible version |
Date |
---|---|---|
Borland C++ Builder 6.4 through 2006, CodeGear C++Builder 2010 | Never worked with Boost.MultiIndex | |
Comeau C/C++ 4.3.10.1 for Windows (VC++ 9.0 backend) | Boost 1.38 | February 2009 |
Compaq C++ 6.5-042 through 7.1-006 for Tru64 UNIX | Boost 1.38 | February 2009 |
GCC 3.2 through 3.4 | Boost 1.41 | November 2009 |
HP aC++ A.06.12 through A.06.17 for HP-UX IA64 | Boost 1.38 | February 2009 |
HP aC++ A.03.80 through A.03.85 for HP-UX PA-RISC | Boost 1.38 | February 2009 |
IBM VisualAge C++ V6.0 for AIX | Boost 1.33.1 | December 2006 |
IBM XL C/C++ V9.0 through V10.1 for AIX | Boost 1.41 | November 2009 |
Intel C++ Compiler for Linux 8.1 through 11.1 | Boost 1.41 | November 2009 |
Intel C++ Compiler for Mac OS 9.1 through 11.0 | Boost 1.41 | November 2009 |
Intel C++ Compiler for Windows 32-bit 8.0 through 11.1 | Boost 1.41 | November 2009 |
Intel C++ Compiler for Windows 64-bit 10.0 through 11.11 | Boost 1.41 | November 2009 |
Metrowerks CodeWarrior 8.3 | Boost 1.36 | August 2008 |
Metrowerks CodeWarrior 9 through 9.5 | Boost 1.34.1 | July 2007 |
Microsoft Visual C++ 6.0 Service Pack 5 | Boost 1.36 | August 2008 |
Microsoft Visual C++ 7.0 | Boost 1.35 | March 2008 |
Sun Studio 10 through 12 Update 1 for Solaris | Boost 1.41 | November 2009 |
Revised January 25th 2020
© Copyright 2003-2020 Joaquín M López Muñoz. Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)