Имам някакъв клас данни, който е скъп за копиране, но трябва да бъде променлив, тъй като често се актуализира според събитията. Имам нужда и от мултииндексен контейнер, за да държа много такива класове. Опитвам се да го настроя с помощта на 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 не се отнася ли за неговия
->
оператор?