boost::call_traits

トップページ > メタプログラミング >

abstract

必要なヘッダ
<boost/call_traits.hpp>
出来ること
関数呼び出しに最適な型を取得
リファレンス
en / jp

sample

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

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

template<typename T>
class Holder
{
public:
	Holder() {}
	typename boost::call_traits<T>::param_type get() { return data; }
	void set( typename boost::call_traits<T>::param_type d ) { data = d; }

private:
	T data;
};

int main()
{
	Holder<int> hint;
	hint.set( 100 );
	int t = hint.get(); // getやsetは const int で受け渡し

	Holder<string> hstr;
	hstr.set( "hoge" );
	string s = hstr.get(); // getやsetは const string& で受け渡し

	return 0;
}

etc

int などの小さな型は関数の引数として渡すときには、 そのまま値渡しにしたほうが普通は効率的です。しかし、例えば vector などのデカブツは毎回コピーしていては大変なことになります。そこで、 あたかも値渡しをしているかのように書けるけれど実際はポインタ渡し並に効率がよい 「const参照」 を用いるというのが、C++では一般的な手段となっています。

さて問題は、int にも vector にも使えるような、 汎用のtemplateを書くとき。型Tの受け渡しはどうすればよいでしょう? const参照にしてしまうことが多いですが、intdouble で使うときを考えると、ちょっと勿体ない気もします。 そこで call_traits<T>::param_type を使うと、 上記の例のように適切な方を選択して使うようにできるわけです。

もう一つ重要な機能として、「参照の参照」の回避があります。 効率がよいからという理由で片っ端からtemplateでconst参照を使っていると、 プログラムの中で「参照型への参照型」が出現してしまうことがよくあります。 で、これはC++的にはイリーガル。「constのconstは唯のconst」にしてくれる C++ が「参照への参照は唯の参照」と扱ってくれないのは猛烈に不満ですが、 現在の所は仕方がない。

解決策としては、「T&」のかわりに 「call_traits<T>::reference」を使うこと。 Tが既に参照型だった場合は call_traits<T>::reference をとっても元の型のままになるように作られているので安心です。

see also

正直、私の下手なサンプルを見るより、 次のページを見た方がまとまっていてわかりやすいです。

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