boost::type_traits

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

abstract

必要なヘッダ
<boost/type_traits.hpp>
出来ること
型に関する情報取得色々
リファレンス
en

sample

#include <cstring>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
#include <boost/type_traits.hpp>
using namespace std;



// copier<false>::do_copy は地道に一個ずつコピーする実装
// copier<true>::do_copy はmemcpyを使って一気にコピーする実装

// memcpyの方がおそらく高速だが、
// 代入演算子を介さないと正しくコピーできない型では
// memcpyは使えない。従ってどちらの実装を用いるかを
// 型に応じてコンパイル時に決定させてみる。


template<bool b>
struct copier
{
	template<typename InIte, typename OutIte>
	static OutIte do_copy(InIte s, InIte e, OutIte x)
	{
		cout << "Iterator version";
		while( s != e )
			*x=*s, ++x, ++s;
		return x;
	}
};

template <>
struct copier<true>
{
	template<typename In, typename Out>
	static Out* do_copy(In* s, In* e, Out* x)
	{
		cout << "MemCpy version";
		memcpy( x, s, (e-s)*sizeof(In) );
		return x+(e-s);
	}
};

template<typename InIte, typename OutIte>
static OutIte myCopy( InIte s, InIte e, OutIte x )
{
	// 比較のためにconst/volatileを外す
	typedef typename boost::remove_cv<
		typename iterator_traits<InIte>::value_type
	>::type v1_t;
	typedef typename boost::remove_cv<
		typename iterator_traits<OutIte>::value_type
	>::type v2_t;

	// memcpyに必要な条件を書き下してANDをとる
	// 両者がconstの違いを除いて同じ型で、両方ともポインタで、
	// 単純なビット毎コピーでの代入が可能ならOK
	typedef copier<
		boost::type_traits::ice_and<
			boost::is_same<v1_t, v2_t>::value,
			boost::is_pointer<InIte>::value,
			boost::is_pointer<OutIte>::value,
			boost::has_trivial_assign<v1_t>::value
		>::value // OKならここが 1 (true) になる
	> impl;

	return impl::do_copy( s, e, x );
}



int main()
{
	{
		// copy実装切り替えのテスト
		vector<string> sa( 10, string("hello") );
		vector<string> sb;
		int ia[10]={1,2,3,4,5,6,7,8,9,10};
		int ib[10];

		cout << "vector<string> copy...";
		myCopy( sa.begin(), sa.end(), back_inserter(sb) );
		cout << endl;

		cout << "int[] copy...";
		myCopy( ia, ia+10, ib );
		cout << endl;
	}
	{
		// もっと簡単な例。intはポインタ型か?int*はポインタ型か?
		cout << boost::is_pointer<int>::value << endl;
		cout << boost::is_pointer<int*>::value << endl;
	}

	return 0;
}

出力例

vector<string> copy...Iterator version
int[] copy...MemCpy version
0
1

etc

is_pointer, is_enum, is_const, has_trivial_copy などの「型一つを受け取って、 ある性質を持っているかどうかを1/0で返す」もの。 is_convertibleなどの「型を二つ受け取って、 その2つがある関係(継承とか変換可能とか)にあるかどうかを1/0で返す」もの。 remove_const, add_reference などの 「型を一つ受け取って、それを加工して別の型として返す」もの、 などがあります。詳しくは本家の リファレンス をご覧下さい。

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