Boost Multi-index Containers Library

Boost Multi-index Containers Library

Posted by Liang Yulai on December 13, 2018

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