Here I have a simple multi_index container and I wonder if there is any way of forcing the multi_index to allocate the elements contiguously in memory. I thought that this would be possible if the main index is random_access
.
However this simple example shows that unexpectedly the elements are not contiguous in memory. Is there a combination of boost::multi_index::indexed_by
that would likely result in contiguous memory?
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/random_access_index.hpp>
int main(){
typedef boost::multi_index_container<
double, // simply store doubles
boost::multi_index::indexed_by<
boost::multi_index::random_access<>
>
> random_access_container;
random_access_container v; // fill container
v.reserve(10); // also tried this
v.push_back(1.);
v.push_back(2.);
v.push_back(3.);
assert( v[0] == 1. ); // ok
assert( *(&v[0] + 1) == v[1] ); // this fails, memory is not contiguous
}
NOTE 1: I want this for compatibility (so I can take advantage of multi_index
container --with other access options--) but also use direct memory access (like it is possible with std::vector
).
NOTE 2: I have just found this quote from the documentation, http://www.boost.org/doc/libs/1_61_0/libs/multi_index/doc/reference/rnd_indices.html#rnd_indices , so it is looking difficult.
Except where noted or if the corresponding interface does not exist, random access indices verify the same container requirements as std::vector plus the requirements for std::list specific list operations at [list.ops]. Some of the most important differences with respect to std::vector are:
Random access indices do not provide memory contiguity, and hence do not have data member functions.
...
No, you don't have memory contiguity. The layout of a random-access index is akin to that of boost::container::stable_vector
:
An approximation to contiguous memory can be obtained if you store your elements (of type say T
) in a std::vector<T>
and then use a multi_index_container
of std::ref<T>
s. This complicates object lifetime management, of course.
Edit: design rationales
There are a number of reasons why memory contiguity is difficult/hard to include in the design of the library:
data()
would return), or b) the nodes would have to be detached from the values, so that rather than embedding the value in the node we'd have nodes with pointers to the contiguously-stored values, which is a waste of space and does not look like a resonable default decision.