# Boost.MultiIndex Compiler specifics

Key extraction
Index
Performance

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.

## Contents

- Move semantics
- Allocator awareness
- Emplace functions
- Initializer lists
- Tuples
- Reduction of symbol name lengths
  - Limitation of maximum number of arguments
  - Type hiding
- Legacy compilers

## Move semantics

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.

## Allocator awareness

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.

## Emplace functions

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.

## Initializer lists

No transparent emulation of this functionality can be provided in the absence of `std::initializer_list`: consider Boost.Assign as a possible replacement.

## Tuples

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.

## Reduction of symbol name lengths

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.

### Limitation of maximum number of arguments

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.

Limiting maximum number of arguments of some class templates of Boost.MultiIndex.
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

### Type hiding

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.

## Legacy compilers

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.

Support for legacy compilers.
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

Key extraction
Index
Performance

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)