四处寻找Boost Multi-Index容器的常量元素

时间:2011-04-03 08:35:47

标签: c++ boost boost-multi-index

我有一些复制成本昂贵的数据类,但必须是可变的,因为它经常根据事件进行更新。我还需要一个多索引容器来容纳许多这样的类。我正在尝试使用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()方法,但使用它看起来很麻烦,因为在我的真实程序中,“payload”类可能包含很多字段,并为每个字段编写一个仿函数。

有什么建议吗?

编辑:经过一番游戏后,我尝试将数据元素替换为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
    ...
}

这几乎给了我想要的东西,但我不确定为什么会这样,所以:

  1. 这段代码是否符合我的意图,或者是否有一些我不知道的警告?
  2. 这是怎么回事? shared_ptr的constness是否不适用于其->运算符?

1 个答案:

答案 0 :(得分:4)

首先,ImMutableAndExpensiveToCopy似乎正好相反 - 可变,因为您试图在示例中更改其内容。试试这个:

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

(并可能更改名称ImMutableAndExpensiveToCopy以保持一致性。)