overview
- introduced in Boost 1.32, released in 2004
- 一个用户自定义的容器,用户可以对其中的数据提供多组访问接口
- 容器定义由 boost::multi_index::multi_index_container 来实现
-
接口的定义由模板类 boost::multi_index::indexed_by 来实现
- Boost.MultiIndex index types
Boost.MultiIndex | STL containers | member function | ||
---|---|---|---|---|
key-based | ordered | ordered_unique | std::set | todo |
key-based | ordered | ordered_non_unique | std::multiset | todo |
key-based | ordered | ranked_unique | ||
key-based | ordered | ranked_non_unique | ||
key-based | hashed | hashed_unique | std::unordered_set | todo |
key-based | hashed | hashed_non_unique | std::unordered_mutiset | todo |
non-key-based | sequenced | std::list | todo | |
non-key-based | random_access |
Why we need multi-index container?
1
2
3
4
5
6
7
8
9
10
struct employee
{
int id;
std::string name;
employee(int id,const std::string& name):id(id),name(name){}
bool operator<(const employee& e)const{return id<e.id;}
};
std::set<employee> employees;
如何实现以 姓名(name)的字母序输出 employees ?
- Copy the employee set into a vector or similar and sort this by a comparison functor dependent upon employee::name.
- Keep a secondary data structure of pointers to the elements of the set, appropriately sorted by name.
用 boost::multi_index 如何实现?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// define a multiply indexed set with indices by id and name
useing employee_set = multi_index_container<
employee,
indexed_by<
// sort by employee::operator<
ordered_unique<identity<employee> >,
// sort by less<string> on name
ordered_non_unique<member<employee,std::string,&employee::name> >
>
>;
void print_out_by_name(const employee_set& es)
{
// get a view to index #1 (name)
const employee_set::nth_index<1>::type& name_index=es.get<1>();
// use name_index as a regular std::set
std::copy(
name_index.begin(), name_index.end(),
std::ostream_iterator<employee>(std::cout));
}
###
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
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/member.hpp>
#include <iostream>
using namespace boost::multi_index;
struct employee
{
int id;
std::string name;
employee(int id,const std::string& name):id(id),name(name){}
bool operator<(const employee& e)const{return id<e.id;}
};
using employee_set = multi_index_container<
employee,
indexed_by<
// sort by employee::operator<
ordered_unique<identity<employee> >,
// sort by less<string> on name
ordered_non_unique<member<employee, std::string, &employee::name> >,
// sequenced<>,
random_access<>
>
>;
int main() {
employee_set es;
es.insert({112, "Charles"});
es.insert({142, "Daniel"});
es.insert({127, "Edward"});
es.insert({123, "Alexander"});
es.insert({122, "Bernard"});
es.insert({23, "Frank"});
es.emplace(110, "Henry");
// es.push_back({100, "James"});
// Henry, James, Kenneth, Leonard, Melvin, Norman
const employee_set::nth_index<0>::type& id_index=es.get<0>();
const employee_set::nth_index<1>::type& name_index=es.get<1>();
const employee_set::nth_index<2>::type& random_index=es.get<2>();
std::cout << "Print the list by id:" << std::endl;
for (auto e:id_index) {
std::cout << e.id << ", " << e.name << std::endl;
}
std::cout << "Print the list by name:" << std::endl;
for (auto e:name_index) {
std::cout << e.id << ", " << e.name << std::endl;
}
std::cout << "Print the list randomly:" << std::endl;
for (auto e:random_index) {
std::cout << e.id << ", " << e.name << std::endl;
}
return 0;
}
####
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
kirin@kawagarbo:~/workspace/repo/test$ make multi_index_2 && ./multi_index_2
g++ multi_index_2.cpp -o multi_index_2
Print the list by id:
23, Frank
110, Henry
112, Charles
122, Bernard
123, Alexander
127, Edward
142, Daniel
Print the list by name:
123, Alexander
122, Bernard
112, Charles
142, Daniel
127, Edward
23, Frank
110, Henry
Print the list randomly:
112, Charles
142, Daniel
127, Edward
123, Alexander
122, Bernard
23, Frank
110, Henry
reference
boost:multi-index boost:multi-index example Why you should use Boost.MultiIndex (Part I) Why you should use Boost.MultiIndex (Part II) The Boost C++ Libraries Boost C++ 库 Boost Dependency Analyzer