【问题标题】:How do I update overlapping indexes in a boost::multi_index_container?如何更新 boost::multi_index_container 中的重叠索引?
【发布时间】:2014-05-29 00:37:00
【问题描述】:

我使用的是 boost 1.48.0,我没有升级选项。

我已经构建了一个 multi_index_container,其中包含具有重叠标准的索引。共享相同索引标准的索引是如何产生影响的,如下例所示?示例代码的最后一行暗示了我的要求。

struct street_address_key : composite_key<
    t_postal_address
    , const_mem_fun<const_mem_fun<t_postal_address, string, &t_postal_address::street_name>>
    , const_mem_fun<const_mem_fun<t_postal_address, long, &t_postal_address::house_number>>
    , const_mem_fun<const_mem_fun<t_postal_address, string, &t_postal_address::city>>
    , const_mem_fun<const_mem_fun<t_postal_address, string, &t_postal_address::state>>
    , const_mem_fun<const_mem_fun<t_postal_address, long, &t_postal_address::zip_code>>
> {};

multi_index<
    t_postal_address
    indexed_by<
        ordered_unique<street_address_key>
        , ordered_non_unique<const_mem_fun<t_postal_address, string, &t_postal_address::name>>
        , ordered_non_unique<const_mem_fun<const_mem_fun<t_postal_address, string, &t_postal_address::street_name>>
        , ordered_non_unique<const_mem_fun<const_mem_fun<t_postal_address, long, &t_postal_address::house_number>>
        , ordered_non_unique<const_mem_fun<const_mem_fun<t_postal_address, string, &t_postal_address::city>>
        , ordered_non_unique<const_mem_fun<const_mem_fun<t_postal_address, string, &t_postal_address::state>>
        , ordered_non_unique<const_mem_fun<const_mem_fun<t_postal_address, long, &t_postal_address::zip_code>>
    >
> t_address_book;

...

t_address_book::nth_element<0>::type::iterator address_iter = book.find(some_address_tuple);

book.modify(address_iter, modify_city_method);

auto city_range = book.get<4>().equal_range( \*???*\ );

城市索引与 street_address_key 具有相同的标准。据我了解,通过 street_address_key 进行修改将确保索引得到适当更新。但“城市”指数的状态如何?是否更新以反映城市名称的变化?还是处于破损状态?我还能找到与旧城区相同的地址索引吗?我必须单独更新这个索引吗?我可以调用 no-op Modifier 来更新索引吗?

// Presume I have the city element from the index.
// Is this supposed to update the city index after it was modified above?

book.get<4>().modify(city_iter, [](t_postal_address &) {});

【问题讨论】:

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


    【解决方案1】:

    作为@sehe cmets,索引都已更新,因此您很安全。补充观察:您的索引 #2

    ordered_non_unique<const_mem_fun<const_mem_fun<t_postal_address, string, &t_postal_address::street_name>>
    

    实际上对于索引#0(基于复合键的索引)是多余的:您可以只将一个字符串(表示街道名称)传递给索引#0,它的行为与索引#2 完全相同。这为您节省了一些空间和执行时间。它背后的魔力在于,当使用复合键时,您可以传递部分信息,直到复合键的第一个元素。

    【讨论】:

    • 这很好。我认为这里没有人知道这一点。我当然没有。希望我可以根据这一事实从我们的生产代码中消除 TWO 索引。谢谢。
    • 看看boost.org/libs/multi_index/doc/tutorial/… 尤其是以“作为符号方便...”开头的段落
    【解决方案2】:

    在我看来应该没有问题:

    文档提到:

    效果:调用 mod(e),其中 e 是 position 指向的元素,并将 *position 重新排列到 multi_index_container 的所有索引中。如果

    则重排成功
    • 索引不唯一或不存在具有等效键的其他元素,
    • multi_index_container 的所有其他索引都允许 AND 重新排列。 如果重新排列失败,则删除该元素。

    这意味着所有索引都已更新。请注意,原则上所有索引都可以拒绝编辑。您可能希望使用回滚来防止数据丢失。

    【讨论】:

    • 也许这是漫长的一天,但我已经看到了这一点,而且在我的一生中,我无法弄清楚这一点。谢谢。
    • @MatthewReddington 我在阅读 boost 文档时也有同样的感觉。不过,这是一个 GoodThing(TM),因为它提醒我要测试。使用“漂亮的 API”很容易陷入虚假的安全感。多索引容器很复杂。复杂性是内在的和不可避免的。复杂性是语义性质的。通过测试确保你知道你的操作是做什么的(在这种情况下,至少有 4 个更新被安排在“一个正方形”中,以使用不连贯、重叠的索引来练习各种情况)
    • 这正是我正在做的。我们在生产软件中使用了 multi_index_container,我怀疑这是性能瓶颈。我正在编写一个测试程序来整体探索替代容器布局和替代数据结构(请让 SQLite3 足够快,请让 SQLite3 足够快,请让 SQLite3 足够快......)。
    • SQLite3 很快,这取决于你如何使用它。性能(或任何扩展)很难,需要仔细规划和调整。也就是说,我只将多索引视为一种方便。我更愿意决定在性能关键场景中何时生成/更新我的索引。
    • 关于 Boost.MultiIndex 的性能,您当然应该针对替代方案进行分析和测试,但总的来说,该库 非常 快。我猜你没有设置安全或不变的检查模式,对吧? boost.org/libs/multi_index/doc/tutorial/debug.html
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-02
    • 2015-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-06
    相关资源
    最近更新 更多