如何调用boost multi_index元素的非常量成员函数

时间:2012-05-25 12:22:35

标签: c++ linux boost

我发布这个是因为我无法理解增强教程的工作原理。

我有一个类,其对象是boost multi_index容器的元素。

我需要使用成员函数更新对象的成员变量。我不知道该怎么做。请问你能帮帮我吗。 我准备了一个简单的例子:

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

using boost::multi_index::multi_index_container;
using boost::multi_index::ordered_non_unique;
using boost::multi_index::ordered_unique;
using boost::multi_index::indexed_by;
using boost::multi_index::member;

class employee_entry
{
public:
   employee_entry( const std::string& first,
                   const std::string& last,
                   long id):
                   first_name_(first),
                   last_name_(last),
                   id_(id)
   {}
   void change(){id_++;}//causing the problem
   std::string first_name_;
   std::string last_name_;
   std::vector<int> mySet;
   long id_;

   std::vector<int>::iterator mySet_begin()  {return mySet.begin();   }
};


typedef multi_index_container<
employee_entry, indexed_by<
   ordered_unique<member<employee_entry, std::string, &employee_entry::first_name_> >
   , ordered_non_unique<member<employee_entry, std::string, &employee_entry::last_name_> >
   , ordered_non_unique<member<employee_entry, long, &employee_entry::id_> >
   >
> employee_set;

//employee set.... multi-index
employee_set m_employees;


int main()
{
   using boost::multi_index::nth_index;
   using boost::multi_index::get;

   typedef nth_index<employee_set, 0>::type first_name_view;
   first_name_view& fnv = get<0>(m_employees);

   fnv.insert(employee_entry("John", "Smith", 110));
   fnv.insert(employee_entry("Fudge", "Hunk", 97));

   ///get employees sorted by id
   typedef nth_index<employee_set, 2>::type id_view;
   id_view& idv = get <2> (m_employees);
   for(id_view::reverse_iterator it = idv.rbegin(), it_end(idv.rend()); it != it_end; ++it)
   {
       std::cout << it->first_name_  <<" "
                 << it->last_name_ << ":"
                 << it->id_ << std::endl;
       it->change();//calling the troublesome function
   }

   return 0;
}

生成的错误是:

 $c++ dr_function.cpp 
dr_function.cpp: In function ‘int main()’:
dr_function.cpp:65:19: error: passing ‘const employee_entry’ as ‘this’ argument of ‘void employee_entry::change()’ discards qualifiers [-fpermissive]

2 个答案:

答案 0 :(得分:2)

您发布的解决方案无法正常工作:最多会出现乱码索引,最糟糕的情况是您的应用会崩溃。由于你的最后一个索引取决于employee_entry::id_,你无法自由地改变它,因为你隐含地破坏了索引顺序。对于这种东西,Boost.MultiIndex提供了更新函数replacemodify,正如所讨论的here。在您的特定情况下,您可以按如下方式调用change成员函数:

idv.modify(idv.iterator_to(*it),boost::bind(&employee_entry::change,_1));

一点解释:idv.iterator_to(*it)只是将反向迭代器转换为常规迭代器,这是modify所需要的。对于boost::bind部分,这将&employee_entry::change封装到合适的修改函子中。通过这种方式,您可以让Boost.MultiIndex了解id_即将发生的变化并相应地更新索引。

答案 1 :(得分:0)

好吧,我正在回答我的问题,至少要调试上面提到的代码。我在这个问题的评论中讨论并回答了我的主要关切。 我是以下代码,我将long id_设为mutable并将void change(){...}更改为void change()const{...}

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

using boost::multi_index::multi_index_container;
using boost::multi_index::ordered_non_unique;
using boost::multi_index::ordered_unique;
using boost::multi_index::indexed_by;
using boost::multi_index::member;

class employee_entry
{
public:
   employee_entry( const std::string& first,
                   const std::string& last,
                   long id):
                   first_name_(first),
                   last_name_(last),
                   id_(id)
   {}
   void change() const {id_++;}//causing the problem
   std::string first_name_;
   std::string last_name_;
   std::vector<int> mySet;
   mutable long id_;

   std::vector<int>::iterator mySet_begin()  {return mySet.begin();   }
};


typedef multi_index_container<
employee_entry, indexed_by<
   ordered_unique<member<employee_entry, std::string, &employee_entry::first_name_> >
   , ordered_non_unique<member<employee_entry, std::string, &employee_entry::last_name_> >
   , ordered_non_unique<member<employee_entry, long, &employee_entry::id_> >
   >
> employee_set;

//employee set.... multi-index
employee_set m_employees;


int main()
{
   using boost::multi_index::nth_index;
   using boost::multi_index::get;

   typedef nth_index<employee_set, 0>::type first_name_view;
   first_name_view& fnv = get<0>(m_employees);

   fnv.insert(employee_entry("John", "Smith", 110));
   fnv.insert(employee_entry("Fudge", "Hunk", 97));

   ///get employees sorted by id
   typedef nth_index<employee_set, 2>::type id_view;
   id_view& idv = get <2> (m_employees);
   for(id_view::reverse_iterator it = idv.rbegin(), it_end(idv.rend()); it != it_end; ++it)
   {
       std::cout << it->first_name_  <<" "
                 << it->last_name_ << ":"
                 << it->id_ << std::endl;
       it->change();//calling the troublesome function
   }

   return 0;
}