I am in a situation where I am forced to use a std::vector
container as my underlying data structure. I'm trying to exploit boost::multi_index::sequenced<>
to shadow the vector offset, and provide a mechanism for richer data queries. I really don't want to unnecessarily copy all the data from one container to another.
In the example code snippet below I have a class BarInterface
that manages the insertion and removal of elements to the Bar::foos
container. Initially I tried to store references to the vector elements as elements of the typedef boost::multi_index_container
, but these are not stable against insertions.
What I'd like to do is have a custom key extractor that is a function of the _bar
container and the boost::multi_index::sequenced<>
index. So, for example to get the name of an element, I'd find the sequence offset x
, and then _bar.foos[x].name
. So, I'm really just using boost::multi_index
as a proxy for richer queries against a vector of variable size.
struct Foo {
std::string name;
};
struct Bar {
std::vector<Foo> foos;
};
class BarInterface {
public:
struct Dummy {};
BarInterface(Bar& bar) : _bar(bar) {
for (auto& foo : bar.foos) {
_idx.get<1>().insert(Dummy{});
}
}
// Index
struct Name {};
typedef boost::multi_index_container<
Dummy, // We're not actually storing anything here
boost::multi_index::indexed_by<
boost::multi_index::sequenced<>, // Kept inline with vector order!
boost::multi_index::ordered_unique<
boost::multi_index::tag<Name>,
// I need something here that takes the boost::multi_index::sequenced<>
// key to get the offset x, and then returns this->_bar.foos[x].name!
>
>
> MultiIndex;
// Insert
void insert(const Foo& foo) {
_bar.foos.push_back(foo);
_idx.get<1>().insert(Dummy{});
}
// Remove
template <typename T>
void remove(T it) {
_bar.foos.erase(_bar.foos.begin() + std::distance(_idx.begin(), _idx.project<0>(it)));
_idx.erase(_idx.project<0>(it));
}
protected:
Bar& _bar;
MultiIndex _idx;
};
I know that boost::multi_index
supports all sorts of key extractors -- for member variables, member functions, global function, etc. However, I can't seem to find an example showing how to generate a key as a function of a boost::multi_index::sequenced<>
index. Is this possible, or is there an elegant alternative?
This is extremely brittle and I wouldn't recommend going to production with such code, but since you asked for it:
Live Coliru Demo
Output