迭代修改boost::multiindex的数据
Iterate and modify the data of boost::multiindex
#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]; });
}
}
#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]; });
}
}