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

时间:2015-02-23 04:33:01

标签: c++ boost

#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的所有内容 但代码无法正常工作(随机行为),我认为当我将修改操作和迭代结合在一起时,我没有得到正确的迭代器。这样做的正确方法是什么?

1 个答案:

答案 0 :(得分:2)

问题是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]; });
    }            
}