У меня есть некоторый класс данных, который стоит скопировать, но он должен быть изменяемым, поскольку он часто обновляется в соответствии с событиями.Мне также нужен многоиндексный контейнер для хранения многих таких классов.Я пытаюсь настроить его, используя boost :: multi_index.Например:
struct MutableAndExpensiveToCopy {
int some_value;
std::map<int, std::string> some_huge_map;
std::map<int, std::string> an_even_bigger_map;
}
struct CanBeMultiIndexed
{
// "Payload" - its fields will never be used as indices
MutableAndExpensiveToCopy data;
// Indexes
int id;
std::string label;
}
typedef multi_index_container<
CanBeMultiIndexed,
indexed_by<
ordered_unique<member<CanBeMultiIndexed, int, &CanBeMultiIndexed::id>>,
ordered_non_unique<member<CanBeMultiIndexed,std::string,&CanBeMultiIndexed::label>>
>
> MyDataContainer;
Моя проблема в том, что multi_index рассматривает элементы в контейнере как константы (чтобы сохранить целостность всех индексов).Например, следующее не будет компилироваться:
void main() {
// put some data in the container
MyDataContainer container;
CanBeMultiIndexed e1(1, "one"); // conto'r not shown in class definition for brevity
CanBeMultiIndexed e2(2, "two");
container.insert(e1);
container.insert(e2);
// try to modify data
MyDataContainer::nth_index<1>::type::iterator iter = container.get<1>().find(1);
iter->data.some_value = 5; // constness violation
}
Я не могу использовать метод replace()
, так как копирование класса полезной нагрузки обходится дорого.Я знаю о методе modify()
, но его использование кажется громоздким, поскольку в моей реальной программе класс «полезной нагрузки» может содержать множество полей, и для каждого из них исключается написание функтора.
Есть предложения?
РЕДАКТИРОВАТЬ: После некоторой игры я попытался заменить элемент данных с shared_ptr на MutableAndExpensiveToCopy
:
struct CanBeMultiIndexed
{
// "Payload" - its fields will never be used as indices
boost::shared_ptr<MutableAndExpensiveToCopy> data;
// Indexes
int id;
std::string label;
}
Это сработало, и я смог скомпилировать main()
, включая код для изменения данных:
void main() {
...
iter->data->some_value = 5; // this works
...
}
Это в значительной степени дает мне то, что я хотел, но я не уверен, почему это работает, поэтому:
- Этот код выполняет то, что я хотел, или есть какое-то предостережение, которое я пропускаю?
- Как это работает?Разве константа shared_ptr не применяется к его оператору
->
?