Getting around Boost Multi-Index container's constant elements

大兔子大兔子 提交于 2019-12-07 22:34:35

问题


I have some data class which is expensive to copy, but must be mutable, as it is frequently updated according to events. I also need a multi-index container to hold many such classes. I'm trying to set it up using boost::multi_index. For example:

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;

My problem is that multi_index treats elements in the container as constants (in order to keep the integrity of all of the indices). For example, the following won't compile:

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
}

I cannot use the replace() method, as it is expensive to copy the payload class. I'm aware of the modify() method, but using it seems cumbersome, since in my real program, the "payload" class may contain numerous fields, and writing a functor for each and every one it out of the question.

Any suggestions?

EDIT: After some playing around, I've tried replacing the data element with a shared_ptr to MutableAndExpensiveToCopy:

struct CanBeMultiIndexed
{
    // "Payload" - its fields will never be used as indices
    boost::shared_ptr<MutableAndExpensiveToCopy> data;

    // Indexes        
    int         id;
    std::string label;
}

This worked, and I was able to compile my main() including the data-modifying code:

void main() {
    ...
    iter->data->some_value = 5;  // this works
    ...
}

This pretty much gives me what I wanted, but I'm not sure why this works, so:

  1. Does this code does what I intended, or is there some caveat I'm missing?
  2. How come this works? Does the constness of the shared_ptr does not apply to its -> operator?

回答1:


First of all, ImMutableAndExpensiveToCopy seems precisely to be the opposite --mutable, since you're trying to change its contents in the example. Try simply this:

struct CanBeMultiIndexed
{
    mutable ImMutableAndExpensiveToCopy data;
    int         id;
    std::string label;
}

(and possibly change the name ImMutableAndExpensiveToCopy for consistency.)



来源:https://stackoverflow.com/questions/5528517/getting-around-boost-multi-index-containers-constant-elements

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!