2009年3月9日月曜日

boost::multi_index で複合キー

たまたま、multi_index コンテナを使ってみたい局面があったので、お題に乗ってみますた。こうやって考えてみると、c++よりも、vbの方がよっぽど難しいのではないかという気もします。最近、便利なもの使いすぎて、頭が馬鹿になってますorz...

#include <iostream>
#include <string>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/key_extractors.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/foreach.hpp>

class program {
private:
std::string country_;
std::string kind_;
public:
program(
const char* country,
const char* kind
) :
country_(country),
kind_(kind)
{
}

const std::string& country() const { return country_; }
const std::string& kind() const { return kind_; }
};

struct country_kind_key : boost::multi_index::composite_key<
program,
boost::multi_index::const_mem_fun< program, const std::string&,
&program::country >,
boost::multi_index::const_mem_fun< program, const std::string&,
&program::kind >
> {};

struct kind_country_key : boost::multi_index::composite_key<
program,
boost::multi_index::const_mem_fun< program, const std::string&,
&program::kind >,
boost::multi_index::const_mem_fun< program, const std::string&,
&program::country >
> {};

struct ck {};
struct kc {};

typedef boost::multi_index::multi_index_container<
program,
boost::multi_index::indexed_by<
boost::multi_index::ordered_unique< boost::multi_index::tag<ck>,
country_kind_key >,
boost::multi_index::ordered_unique< boost::multi_index::tag<kc>,
kind_country_key >
>
> program_set;

typedef program_set::index<ck>::type program_ck_type;
typedef program_set::index<kc>::type program_kc_type;

int main() {
program_set programs;

programs.insert( program("US", "マラソン") );
programs.insert( program("JP", "マラソン") );
programs.insert( program("UK", "マラソン") );
programs.insert( program("CH", "マラソン") );
programs.insert( program("US", "100m") );
programs.insert( program("JP", "100m") );
programs.insert( program("UK", "100m") );
programs.insert( program("JP", "400m") );
programs.insert( program("US", "400m") );
programs.insert( program("US", "砲丸投げ") );

BOOST_FOREACH( const program& p, programs.get<ck>() ) {
std::cout << "国:" << p.country() << ",種目:" << p.kind() << std::endl;
}

boost::tuple<const std::string, const std::string> skey("100m","");
boost::tuple<const std::string, const std::string> ekey("100m-", ""); // かっこ悪い

program_kc_type::iterator kb = programs.get<kc>().lower_bound( skey );
program_kc_type::iterator ke = programs.get<kc>().lower_bound( ekey );
while( kb != ke ) {
std::cout << "種目:" << (*kb).kind() << ",国:" << (*kb).country() << std::endl;
++kb;
}

return 0;
}

0 件のコメント: