multi_index composite_key替换为迭代器

时间:2010-05-13 13:41:26

标签: replace composite-key multi-index

无论如何都要在boost :: multi_index中循环索引并执行替换吗?

#include <iostream>
#include <string>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>

using namespace boost::multi_index;
using namespace std;

struct name_record
{

  public:

  name_record(string given_name_,string family_name_,string other_name_)
  {
      given_name=given_name_;
      family_name=family_name_;
      other_name=other_name_;
  }

  string given_name;
  string family_name;
  string other_name;

  string get_name() const { return given_name + " " + family_name + " " + other_name; }

  void setnew(string chg)
  {
      given_name = given_name + chg;
      family_name = family_name + chg;
  }

};

struct NameIndex{};

typedef multi_index_container<
  name_record,
  indexed_by<
    ordered_non_unique<
      tag<NameIndex>,
      composite_key
      <
        name_record,
        BOOST_MULTI_INDEX_MEMBER(name_record,string, name_record::given_name),
        BOOST_MULTI_INDEX_MEMBER(name_record,string, name_record::family_name)
      >
    >
  >
> name_record_set;

typedef boost::multi_index::index<name_record_set,NameIndex>::type::iterator IteratorType;
typedef boost::multi_index::index<name_record_set,NameIndex>::type NameIndexType;

void printContainer(name_record_set & ns)
{
  cout << endl << "PrintContainer" << endl << "-------------" << endl;
  IteratorType it1 = ns.begin();
  IteratorType it2 = ns.end  ();

  while (it1 != it2)
  {
       cout<<it1->get_name()<<endl;
       it1++;
  }
  cout << "--------------" << endl << endl;

}


void modifyContainer(name_record_set & ns)
{
  cout << endl << "ModifyContainer" << endl << "-------------" << endl;
  IteratorType it3;
  IteratorType it4;

  NameIndexType & idx1 = ns.get<NameIndex>();
  IteratorType it1 = idx1.begin();
  IteratorType it2 = idx1.end();

  while (it1 != it2)
  {
        cout<<it1->get_name()<<endl;
        name_record nr = *it1;

        nr.setnew("_CHG");
        bool res = idx1.replace(it1,nr);
        cout << "result is: " << res << endl;
        it1++;
  }
  cout << "--------------" << endl << endl;
}

int main()
{
  name_record_set ns;

  ns.insert( name_record("Joe","Smith","ENTRY1")          );
  ns.insert( name_record("Robert","Brown","ENTRY2")       );
  ns.insert( name_record("Robert","Nightingale","ENTRY3") );
  ns.insert( name_record("Marc","Tuxedo","ENTRY4")        );

  printContainer  (ns);
  modifyContainer (ns);
  printContainer  (ns);

  return 0;
}



PrintContainer
-------------
Joe Smith ENTRY1
Marc Tuxedo ENTRY4
Robert Brown ENTRY2
Robert Nightingale ENTRY3
--------------


ModifyContainer
-------------
Joe Smith ENTRY1
result is: 1
Marc Tuxedo ENTRY4
result is: 1
Robert Brown ENTRY2
result is: 1
--------------


PrintContainer
-------------
Joe_CHG Smith_CHG ENTRY1
Marc_CHG Tuxedo_CHG ENTRY4
Robert Nightingale ENTRY3
Robert_CHG Brown_CHG ENTRY2
--------------

1 个答案:

答案 0 :(得分:1)

while (it1 != it2)
{
      cout<<it1->get_name()<<endl;
      name_record nr = *it1;

      nr.setnew("_CHG");
      bool res = idx1.replace(it1,nr);
      cout << "result is: " << res << endl;
      it1++;
}

此代码的问题在于,一旦您替换了元素x,它就会自动重新排序到新位置,以便it1继续指向x ,“跳过”序列,可能会跳过或重新访问元素。

解决方案是在开始替换之前添加一个间接级别并将迭代器收集到所有元素:

#include <vector>
#include <boost/iterator/counting_iterator.hpp>

void modifyContainer(name_record_set & ns)
{
  cout << endl << "ModifyContainer" << endl << "-------------" << endl;

  NameIndexType & idx1 = ns.get<NameIndex>();
  std::vector<IteratorType> v(
    boost::make_counting_iterator(idx1.begin()),
    boost::make_counting_iterator(idx1.end()));
  std::vector<IteratorType>::iterator it1=v.begin(),
                                      it2=v.end();

  while (it1 != it2)
  {
        cout<<(*it1)->get_name()<<endl;
        name_record nr = **it1;

        nr.setnew("_CHG");
        bool res = idx1.replace(*it1,nr);
        cout << "result is: " << res << endl;
        it1++;
  }
  cout << "--------------" << endl << endl;
}

如果您以前没有使用它,make_counting_iterator位只是一种使用迭代器将向量填充到ns的所有元素的简洁方法。