boost.png (6897 bytes)Boost.MultiIndex Index reference



Contents

Index concepts

multi_index_container instantiations comprise one or more indices specified at compile time. Each index allows read/write access to the elements contained in a definite manner. For instance, ordered indices provide a set-like interface to the elements, whereas sequenced indices mimic the functionality of std::list.

Indices are not isolated objects, and so cannot be constructed on their own. Rather they are embedded into a multi_index_container as specified by means of an index specifier. The name of the index class implementation proper is never directly exposed to the user, who has only access to the associated index specifier.

Insertion and erasing of elements are always performed through the appropriate interface of some index of the multi_index_container; these operations, however, do have an impact on all other indices as well: for instance, insertion through a given index may fail because there exists another index which bans the operation in order to preserve its invariant (like uniqueness of elements.) This circumstance, rather than being an obstacle, yields much of the power of Boost.MultiIndex: equivalent constructions based on manual composition of standard containers would have to add a fair amount of code in order to globally preserve the invariants of each container while guaranteeing that all of them are synchronized. The global operations performed in a joint manner among the various indices can be reduced to six primitives:

The last two primitives deserve some further explanation: in order to guarantee the invariants associated to each index (e.g. some definite ordering,) elements of a multi_index_container are not mutable. To overcome this restriction, indices expose member functions for updating and modifying, which allow for the mutation of elements in a controlled fashion. Immutability of elements does not significantly impact the interface of ordered indices, as it is based upon that of std::set and std:multiset, and these containers also have non-mutable elements; but it may come as a surprise when dealing with sequenced indices, which are designed upon the functionality provided by std::list.

These global operations are not directly exposed to the user, but rather they are wrapped as appropriate by each index (for instance, ordered indices provide a set-like suite of insertion member functions, whereas sequenced and random access indices have push_back and push_front operations.) Boost.MultiIndex poses no particular conditions on the interface of indices, save that they must model Container (without the requirement of being Assignable.)

Complexity signature

Some member functions of an index interface are implemented by global primitives from the list above. Complexity of these operations thus depends on all indices of a given multi_index_container, not just the currently used index.

In order to establish complexity estimates, an index is characterized by its complexity signature, consisting of the following associated functions on the number of elements:

Each function yields the complexity estimate of the contribution of the index to the corresponding global primitive. Let us consider an instantiation of multi_index_container with N indices labelled 0,...,N-1 whose complexity signatures are (ci,ii,hi,di,ri,mi); the insertion of an element in such a container is then of complexity O(i0(n)+···+iN-1(n)) where n is the number of elements. To abbreviate notation, we adopt the following definitions: For instance, consider a multi_index_container with two ordered indices, for which i(n)=log(n), and a sequenced index with i(n)=1 (constant time insertion). Insertion of an element into this multi_index_container is then of complexity
O(I(n))=O(2*log(n)+1)=O(log(n)).

Index specification

Index specifiers are passed as instantiation arguments to multi_index_container and provide the information needed to incorporate the corresponding indices. Future releases of Boost.MultiIndex may allow for specification of user-defined indices. Meanwhile, the requirements for an index specifier remain implementation defined. Currently, Boost.MultiIndex provides the index specifiers

Header "boost/multi_index/indexed_by.hpp" synopsis

namespace boost{

namespace multi_index{

template<typename T0,...,typename Tn>
struct indexed_by;

} // namespace boost::multi_index 

} // namespace boost

Class template indexed_by

indexed_by is a model of MPL Random Access Sequence and MPL Extensible Sequence meant to be used to specify a compile-time list of indices as the IndexSpecifierList of multi_index_container.

template<typename T0,...,typename Tn>
struct indexed_by;

Each user-provided element of indexed_list must be an index specifier. At least an element must be provided. The maximum number of elements of an indexed_by sequence is implementation defined.

Tags

Tags are just conventional types used as mnemonics for indices of an multi_index_container, as for instance in member function get. Each index can have none, one or more tags associated. The way tags are assigned to a given index is dependent on the particular index specifier. However, for convenience all indices of Boost.MultiIndex support tagging through the class template tag.

Header "boost/multi_index/tag.hpp" synopsis

namespace boost{

namespace multi_index{

template<typename T0,...,typename Tn>
struct tag;

} // namespace boost::multi_index 

} // namespace boost

Class template tag

tag is a typelist construct used to specify a compile-time sequence of tags to be assigned to an index in instantiation time.

template<typename T0,...,typename Tn>
struct tag
{
  typedef implementation defined type;
};

Elements of tag can be any type, though the user is expected to provide classes with mnemonic names. Duplicate elements are not allowed. The maximum number of elements of a tag instantiation is implementation defined. The nested type is a model of MPL Random Access Sequence and MPL Extensible Sequence containing the types T0, ... , Tn in the same order as specified.

Indices provided by Boost.MultiIndex

Key-based indices

Indices of this type are organized around keys obtained from the elements, as described in the key extraction reference.

Other types

Index views

The following concept is used by the rearrange facilities of non key-based indices. Given an index i of type Index, a view of i is any range [first,last) where first and last are objects of a type Iterator modelling Input Iterator such that

  1. the associated value type of Iterator is convertible to const Index::value_type&
  2. and each of the elements of i appears exactly once in [first,last).
Note that the view refers to the actual elements of i, not to copies of them. Additionally, a view is said to be free if its traversal order is not affected by changes in the traversal order of i. Examples of free views are:




Revised July 21st 2009

© Copyright 2003-2009 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)