user defined tagsを用いたBoost.BimapとBoost.Foreachを組み合わせて使う

どの型をtypedefしてどれをBoost.Foreachに渡せばいいのかよく分からなかったのでメモ.

#include <iostream>
#include <boost/foreach.hpp>
#include <boost/bimap/bimap.hpp>
#include <boost/bimap/multiset_of.hpp>
using namespace std;

struct name {};
struct place {};

int main(int argc, char const* argv[]) {
  using namespace boost::bimaps;

  typedef bimap<
    tagged<string, name>,
    multiset_of<tagged<string, place> >
  > address_map;

  typedef address_map::value_type address;
  typedef address_map::map_by<name>::value_type by_name;
  typedef address_map::map_by<place>::value_type by_place;

  address_map a;

  a.insert(address("mickey24", "Tokyo"));
  a.insert(address("wakuteka", "Tokyo"));
  a.insert(address("syou6162", "Tsukuba"));

  cout << "syou6162 => " << a.by<name>().at("syou6162") << endl;
  cout << endl;

  cout << "sort by name:" << endl;
  BOOST_FOREACH(by_name& i, a.by<name>()) {
    cout << i.get<name>() << " => " << i.get<place>() << endl;
  }
  cout << endl;

  cout << "sort by place:" << endl;
  BOOST_FOREACH(by_place& i, a.by<place>()) {
    cout << i.get<name>() << " => " << i.get<place>() << endl;
  }
  cout << endl;

  cout << "list members where place = Tokyo:" << endl;
  BOOST_FOREACH(by_place& i, a.by<place>().equal_range("Tokyo")) {
    cout << i.get<name>() << " => " << i.get<place>() << endl;
  }

  return 0;
}

出力は以下の通り.

syou6162 => Tsukuba

sort by name:
mickey24 => Tokyo
syou6162 => Tsukuba
wakuteka => Tokyo

sort by place:
mickey24 => Tokyo
wakuteka => Tokyo
syou6162 => Tsukuba

list members where place = Tokyo:
mickey24 => Tokyo
wakuteka => Tokyo

うまくtypedefすればある程度すっきり書ける.