Just take a simple note here.
The Boost Multi-index Containers Library provides a class template named multi_index_container
which enables the construction of containers maintaining one or more indices with different sorting and access semantics.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
#include <string> #include <ostream> #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/tag.hpp> #include <boost/lambda/lambda.hpp> using namespace std; using namespace boost::multi_index; struct auth { string m_name; string m_pass; auth(const string &name, const string &pass) : m_name(name), m_pass(pass) { } bool operator<(const auth &o) const { return m_name < o.m_name; } friend ostream &operator<<(ostream &os, const auth &a) { os << "(" << a.m_name << ", " << a.m_pass << ")"; return os; } }; struct employee { int m_id; auth m_auth; int m_hire; int m_resign; employee(int id, const string &name, const string &pass, int hire, int resign) : m_id(id), m_auth(name, pass), m_hire(hire), m_resign(resign) { } bool operator<(const employee &o) const { return m_id < o.m_id; } friend ostream &operator<<(ostream &os, const employee &e) { os << "(" << e.m_id << ", " << e.m_auth << ", " << e.m_hire << ", " << e.m_resign << ")"; return os; } }; struct auth_t { }; struct change_resign { int m_resign; change_resign(int r) : m_resign(r) { } void operator()(employee &e) { e.m_resign = m_resign; } }; typedef multi_index_container< employee, indexed_by< /* sort by employee::operator< */ ordered_unique<identity<employee> >, /* sort by less<int> on m_hire */ ordered_non_unique<member<employee, int, &employee::m_hire> >, /* sort by less<auth> on m_auth */ ordered_non_unique<tag<auth_t>, member<employee, auth, &employee::m_auth> > > > employee_set; int main() { employee_set es; es.insert(employee(1, "555", "555pass", 2012, 0)); es.insert(employee(2, "444", "444pass", 2011, 0)); es.insert(employee(3, "333", "333pass", 2013, 0)); es.insert(employee(4, "222", "222pass", 2015, 0)); es.insert(employee(5, "555", "555pass", 2014, 0)); /* dup */ typedef employee_set::nth_index<1>::type hire_index_t; typedef employee_set::index<auth_t>::type auth_index_t; cout << "Get a view to index #1 (m_hire).." << endl; hire_index_t &hire_index = es.get<1>(); std::copy(hire_index.begin(), hire_index.end(), ostream_iterator<employee>(cout, "\n")); cout << "Get a view to index tag auth_t (m_auth).." << endl; const auth_index_t &auth_index = es.get<auth_t>(); std::copy(auth_index.begin(), auth_index.end(), ostream_iterator<employee>(cout, "\n")); cout << "Find.." << endl; hire_index_t::iterator it = hire_index.find(2015); #if 0 employee t = *it; t.m_resign = 2048; hire_index.replace(it, t); #else hire_index.modify_key(it, boost::lambda::_1=1111); int old_resign = it->m_resign; hire_index.modify(it, change_resign(2048), change_resign(old_resign)); #endif cout << (*it) << endl; cout << "Find all.." << endl; pair<auth_index_t::const_iterator, auth_index_t::const_iterator> pr = auth_index.equal_range(auth("555", "")); std::copy(pr.first, pr.second, ostream_iterator<employee>(cout, "\n")); return 0; } |
Output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
Get a view to index #1 (m_hire).. (2, (444, 444pass), 2011, 0) (1, (555, 555pass), 2012, 0) (3, (333, 333pass), 2013, 0) (5, (555, 555pass), 2014, 0) (4, (222, 222pass), 2015, 0) Get a view to index tag auth_t (m_auth).. (4, (222, 222pass), 2015, 0) (3, (333, 333pass), 2013, 0) (2, (444, 444pass), 2011, 0) (1, (555, 555pass), 2012, 0) (5, (555, 555pass), 2014, 0) Find.. (4, (222, 222pass), 1111, 2048) Find all.. (1, (555, 555pass), 2012, 0) (5, (555, 555pass), 2014, 0) |
To use with pointer values, only limited change needed as highlighted:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
#include <string> #include <ostream> #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/tag.hpp> #include <boost/lambda/lambda.hpp> using namespace std; using namespace boost::multi_index; struct auth { string m_name; string m_pass; auth(const string &name, const string &pass) : m_name(name), m_pass(pass) { } bool operator<(const auth &o) const { return m_name < o.m_name; } friend ostream &operator<<(ostream &os, const auth &a) { os << "(" << a.m_name << ", " << a.m_pass << ")"; return os; } }; struct employee { int m_id; auth m_auth; int m_hire; int m_resign; employee(int id, const string &name, const string &pass, int hire, int resign) : m_id(id), m_auth(name, pass), m_hire(hire), m_resign(resign) { } bool operator<(const employee &o) const { return m_id < o.m_id; } friend ostream &operator<<(ostream &os, const employee *e) { os << "(" << e->m_id << ", " << e->m_auth << ", " << e->m_hire << ", " << e->m_resign << ")"; return os; } }; struct auth_t { }; struct change_resign { int m_resign; change_resign(int r) : m_resign(r) { } void operator()(employee *e) { e->m_resign = m_resign; } }; typedef multi_index_container< employee *, indexed_by< /* sort by employee::operator< */ ordered_unique<identity<employee> >, /* sort by less<int> on m_hire */ ordered_non_unique<member<employee, int, &employee::m_hire> >, /* sort by less<auth> on m_auth */ ordered_non_unique<tag<auth_t>, member<employee, auth, &employee::m_auth> > > > employee_set; int main() { employee_set es; es.insert(new employee(1, "555", "555pass", 2012, 0)); es.insert(new employee(2, "444", "444pass", 2011, 0)); es.insert(new employee(3, "333", "333pass", 2013, 0)); es.insert(new employee(4, "222", "222pass", 2015, 0)); es.insert(new employee(5, "555", "555pass", 2014, 0)); /* dup */ typedef employee_set::nth_index<1>::type hire_index_t; typedef employee_set::index<auth_t>::type auth_index_t; cout << "Get a view to index #1 (m_hire).." << endl; hire_index_t &hire_index = es.get<1>(); std::copy(hire_index.begin(), hire_index.end(), ostream_iterator<employee *>(cout, "\n")); cout << "Get a view to index tag auth_t (m_auth).." << endl; const auth_index_t &auth_index = es.get<auth_t>(); std::copy(auth_index.begin(), auth_index.end(), ostream_iterator<employee *>(cout, "\n")); cout << "Find.." << endl; hire_index_t::iterator it = hire_index.find(2015); #if 0 employee *t = *it; t->m_auth.m_name = "888"; /* must use replace() to notify changes in indexed fields */ hire_index.replace(it, t); #else hire_index.modify_key(it, boost::lambda::_1=1111); int old_resign = (*it)->m_resign; hire_index.modify(it, change_resign(2048), change_resign(old_resign)); #endif cout << (*it) << endl; cout << "Find all.." << endl; pair<auth_index_t::const_iterator, auth_index_t::const_iterator> pr = auth_index.equal_range(auth("555", "")); std::copy(pr.first, pr.second, ostream_iterator<employee *>(cout, "\n")); /* clear */ for (employee_set::const_iterator it = es.begin(); it != es.end(); ++it) { delete *it; } employee_set().swap(es); return 0; } |