迭代和修改 boost::multiindex 的数据

Iterate and modify the data of boost::multiindex

本文关键字:multiindex 数据 boost 修改 迭代      更新时间:2023-10-16
#include "modify_example.hpp"
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <iostream>
#include <string>
using namespace boost::multi_index;
namespace{
struct name{};
struct email{};
struct employee
{
    std::string email_;
    std::string name_;
    employee(std::string name, std::string email) :
        email_(email),
        name_(name)
    {}
};
using DispatchUsersTable =
multi_index_container
<
  employee,
  indexed_by
  <
    ordered_unique
    <
      tag<name>, member
      <employee, std::string, &employee::name_>
    >,
    ordered_unique
    <
      tag<email>, member
      <employee, std::string, &employee::email_>
    >
  >
>;
}
void order_after_modify()
{
    DispatchUsersTable table;
    table.insert(employee{"jk", "http:cat"});
    table.insert(employee{"otaku", "http:joker"});
    table.insert(employee{"cba", "http:amota"});
    //auto will make codes much easier to read
    //I type the type explicitly because I need to
    //maintain the codes created by c++98
    using Table = DispatchUsersTable::index<name>::type;
    using Iterator = Table::iterator;
    std::vector<std::string> names{"doremi", "onpu", "aichan"};
    size_t num = 0;
    for(Iterator it = table.get<name>().begin();
        it != table.get<name>().end(); ){
        std::cout<<it->name_<<", "<<it->email_<<std::endl;
        name_index.modify(it++, [&](employee &e){ e.name_ = names[num++]; });
    }            
}

我想通过 for 循环修改multi_index的所有内容但是代码无法正常工作(随机行为(,我认为当我将修改操作和迭代组合在一起时,我没有得到正确的迭代器。正确的方法是什么?

问题是modify在此过程中更改元素的顺序,因此迭代可能会以相当不可预测的方式重新访问或跳过过去的元素。解决方案是在进行修改之前存储迭代器:

void order_after_modify()
{
    DispatchUsersTable table;
    table.insert(employee{"jk", "http:cat"});
    table.insert(employee{"otaku", "http:joker"});
    table.insert(employee{"cba", "http:amota"});
    //auto will make codes much easier to read
    //I type the type explicitly because I need to
    //maintain the codes created by c++98
    using Table = DispatchUsersTable::index<name>::type;
    using Iterator = Table::iterator;
    Table& name_index= table.get<name>();
    std::vector<std::string> names{"onpu", "doremi", "aichan"};
    std::vector<Iterator> view;
    for(Iterator it = table.get<name>().begin();it != table.get<name>().end(); ++it){
      view.push_back(it);
    }
    for(size_t num = 0;num<view.size();++num){
       std::cout<<view[num]->name_<<", "<<view[num]->email_<<std::endl;
       name_index.modify(view[num], [&](employee &e){ e.name_ = names[num]; });
    }            
}