boost::multi_index

トップページ > コンテナとイテレータ >

abstract

必要なヘッダ
<boost/multi_index_container.hpp> (基本),
<boost/multi_index/ordered_index.hpp> ((multi)set風アクセス),
<boost/multi_index/hashed_index.hpp> (unordered_(multi)set風アクセス),
<boost/multi_index/sequenced.hpp> (list風アクセス),
<boost/multi_index/random_access_index.hpp> (vector風アクセス)
出来ること
複数のアクセス手段を提供するコンテナ
リファレンス
en

sample

サンプルの動作確認バージョン [GCC4.4/1.41.0] [VC9/1.41.0]

#include <iostream>
#include <string>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/foreach.hpp>              // 以下のサンプル中でBoost.Foreach使ってます
using namespace std;
using namespace boost::multi_index;

int main()
{
	typedef multi_index_container<string, // std::stringを格納するコンテナ
	   indexed_by<
	     sequenced<>,                           // std::list風の入れた順番アクセス
	     ordered_non_unique< identity<string> > // std::multiset風のソート順アクセス
	                                            //  ソートは入れたstringの値そのものを使って行う
	  >
	> container;

	// まず、1つめに指定したアクセス手段(sequenced<>)を持つコンテナとして普通に使える
	container c;
	c.push_back("This");
	c.push_back("Is");
	c.push_back("A");
	c.push_back("Pen");
	c.push_back("That");
	c.push_back("Is");
	c.push_back("Also");
	c.push_back("A");
	c.push_back("Pen");

	BOOST_FOREACH( const string& s, c )
		cout << s << ' ';
	cout << endl;

	// 別のindex(ordered_non_unique...)でアクセスしたい場合は、get<番号>
	container::nth_index<1>::type& c1 = c.get<1>();
	BOOST_FOREACH( const string& s, c1 )
		cout << s << ' ';
	cout << endl;

	// set風に使用(O(logN)で実行される)
	cout << c1.count("Pen") << endl;

	// set風に使用(O(logN)で実行される)
	c1.erase("Is");

	// あるindexから実行した操作は、別のindexにも反映されてる
	BOOST_FOREACH( const string& s, c )
		cout << s << ' ';
	cout << endl;
}

実行結果

This Is A Pen That Is Also A Pen
A A Also Is Is Pen Pen That This
2
This A Pen That Also A Pen

etc

1つのデータ集合を複数の見方でアクセスしたいことがあります。

などなど。とりあえずstd::listとかに突っ込んでおいて、ソートが必要になったら毎回std::sortをかけるとか、 存在判定は仕方ないので全要素ループを回して判定、という手はあります。 ただ、それはとても最適とは言えないので、パフォーマンス上の問題になるかもしれません。 そんな時に、multi_index_containerを使います。

「list風とset風の2通りでアクセスしたいなら、listとsetの2つ用意して両方にデータを入れていく」 というアプローチとの違いは、サンプルのeraseの例であげたように、 全てのindexでちゃんと中身の同期がとれる辺りです。単純にlistとsetを2つ用意するだけでは、 eraseをO(logN)で処理することはできません。 計算量に関しての詳細は リファレンス 参照のこと。

see also

presented by k.inaba (kiki .a.t. kmonos.net) under CC0