boost::compressed_pair

トップページ > 小道具 >

abstract

必要なヘッダ
<boost/compressed_pair.hpp>
出来ること
メモリ節約版std::pair
リファレンス
en

sample

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

#include <iostream>
#include <string>
#include <boost/compressed_pair.hpp>
using namespace std;

int main()
{
	// std::pairと全く同様に使えます。
	boost::compressed_pair<string, int> taro( "太郎", 30 );
	cout << "Name: " << taro.first() << endl;
	cout << "Age: " << taro.second() << endl;

	// このpairの中身に空クラスが入ってくるような場合なら、
	// std::pairよりサイズが小さくなってお得なのですが
	// intとstringじゃ全然関係ないですね。(^^; 

	return 0;
}

etc

iteratorだとかtraitsだとかfunction objectを使ったプログラムを書いていると、 メンバ変数も仮想関数も1個も持たない、いわゆる空のクラスが出来ることがあります。 空のクラスであっても、アドレスは一意に決めなくてはならないので、 sizeof( EmptyClass ) は 0 にはなりません。


EmptyClass arr[100];
assert( &arr[0] != &arr[1] ); // アドレスは違ってて欲しい

従って、普通の std::pairstd::pair<int, EmptyClass> のように空クラスをメンバに持つと、 pairのメモリ消費がEmptyClassの分無駄に増えてしまいかねません。

この余剰消費を削るには「空の基底クラスは最適化してサイズ0として扱ってもよい」 というルールを利用して、こんな感じにprivate継承でデータを持ってしまえば、 コンパイラの最適化の度合いによってはメモリ消費を軽減できます。

template<> class compressed_pair<T1, EmptyClass> : EmptyClass {
	T1 first;
};

// template<> class pair<T1, EmptyClass> {
//	T1 first;  EmptyClass second;
// };

使いどころは極めて少ないでしょう。1.28.0時点では、boost内でも一カ所だけ (iterator_adaptorsで Base と Policy をペアで持って可能ならPolicyの分のサイズを節約)しか使われていません。 iteratorならば生ポインタと同じくらい気軽にコピーしたいので、 極限まで節約しようというのはわかります。が、 そのくらい気合いを入れるところでなければ、このクラスは使う必要はないと思います。

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