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