<boost/type_traits.hpp>の内容はboost名前空間内で宣言される。
ファイル<boost/type_traits.hpp>は、型の基本的な特徴を説明する様々なテンプレートクラスを含んでいる。 各クラスは単一の型の特徴または単一の型の変形を意味する。本ライブラリに不慣れであれば、付随する記事を最初に読むこと。
このドキュメントは以下のセクションに分割される。
Primary Type Categorisation Secondary Type Categorisation Type Properties Relationships Between Types Transformations Between Types Synthesizing Types Function Traits Compiler Support Information Type traits headers Example Code
本ライブラリにおける汎整数式はすべて汎整数定数式である。それらの使用は時折コンパイラの問題に遭遇する原因となるため, 本ライブラリを用いて移植性のあるコードを書くための手引きとしてコーディングガイドラインに関連した事項がある。
以下の型特性(type traits)テンプレートは型がどの型分類に属しているかを識別する。どんな型を与えた場合でも、以下の式のうちのひとつは確実に真に評価される。
is_integral<T>::value
とis_float<T>::value
は組み込み型についてのみ当てはまることに注意。あたかも汎整数型や浮動小数点型のように振舞うユーザ定義型を調べるのであれば、代わりにstd::numeric_limitsテンプレートを使うこと。
Expression |
Description |
Reference |
Compiler requirements |
||
::boost::is_void<T>::value |
Tがconst/volatile修飾されたvoid型であれば真に評価する。 | 3.9.1p9 |
|||
::boost::is_integral<T>::value |
Tがconst/volatile修飾された汎整数型であれば真に評価する。 | 3.9.1p7 |
|||
::boost::is_float<T>::value |
Tがconst/volatile修飾された浮動小数点型であれば真に評価する。 | 3.9.1p8 |
|||
::boost::is_pointer<T>::value |
Tがconst/volatile修飾されたポインタ型であれば真に評価する(関数ポインタは含まれるが、メンバへのポインタは含まない)。 | 3.9.2p2 8.3.1 |
|||
::boost::is_reference<T>::value |
Tが参照型であれば真に評価する。 | 3.9.2 8.3.2 |
|||
::boost::is_member_pointer<T>::value |
Tがconst/volatile修飾されたデータメンバまたはメンバ関数へのポインタであれば真に評価する。 | 3.9.2 8.3.3 |
|||
::boost::is_array<T>::value |
Tが配列型であれば真に評価する。 | 3.9.2 8.3.4 |
コンパイラがクラステンプレートの部分特殊化版をサポートしていない場合、型によっては間違って配列と認識されることがある(主に関数型)。 | ||
::boost::is_union<T>::value |
Tが共用体型であれば真に評価する。現時点ではある種のコンパイラのサポートを必要とし、それ以外では共用体はクラスとして識別される。 | 3.9.2 9.5 |
C | ||
::boost::is_class<T>::value |
Tがクラス/構造体型であれば真に評価する。 | 3.9.2 9.2 |
C | ||
::boost::is_enum<T>::value |
Tが列挙型であれば真に評価する。 | 3.9.2 7.2 |
is_convertibleテンプレートが正しく機能することが必要(現時点ではis_enumがBorland C++では使えないという意味)。 | ||
::boost::is_function<T>::value |
Tが関数型であれば真に評価する(関数への参照やポインタではない)。 | 3.9.2p1 8.3.5 |
部分特殊化版がサポートされない場合、このテンプレートは参照型についてはコンパイルできない。 |
以下の型分類は1つ以上のprimary type categorisationsを組み合わせて作られている。ある型は、primary type categorisationsの分類に加えて、これらの分類のうちの1つ以上に属している可能性がある。
Expression |
Description |
Reference |
Compiler requirements |
||
::boost::is_arithmetic<T>::value |
Tがconst/volatile修飾された算術型であれば真に評価する。汎整数型か浮動小数点型のいずれかがこれにあたる。 | 3.9.1p8 |
|||
::boost::is_fundamental<T>::value |
Tがconst/volatile修飾された基本型であれば真に評価する。汎整数型、浮動小数点型、void型のいずれかがこれにあたる。 | 3.9.1 |
|||
::boost::is_object<T>::value |
Tがconst/volatile修飾されたオブジェクト型であれば真に評価する。関数型、参照型、void型以外がこれにあたる。 | 3.9p9 |
|||
::boost::is_scalar<T>::value |
Tがconst/volatile修飾されたスカラ型であれば真に評価する。算術型、ポインタ型、メンバへのポインタ型がこれにあたる。 | 3.9p10 |
|||
::boost::is_compound<T>::value |
Tが複合型であれば真に評価する。関数型、ポインタ型、参照型、列挙型、共用体型、クラス型、メンバ関数型がこれにあたる。 | 3.9.2 |
|||
::boost::is_member_function_pointer<T>::value |
Tがメンバ関数へのポインタ型(メンバオブジェクトへのポインタではない)であれば真に評価する。このテンプレートはis_member_pointerを2つの副分類に分割する。 | 3.9.2 8.3.3 |
以下のテンプレートは型が持っている特徴を識別する。
Expression |
Description |
Reference |
Compiler requirements |
||
::boost::alignment_of<T>::value |
Tが必要とするアラインメントを識別する。実際に返される値は、Tが必要とする実際のアラインメントの倍数となることが保証される。 | ||||
::boost::is_empty<T>::value |
Tが空の構造体やクラスである場合に真。コンパイラが"空の基底クラスのサイズを0にする"最適化を実装しているのであれば、is_emptyはTが空であることを正しく推察する。 is_classがTがクラス型であることを判別できることが前提。 | 10p5 |
PCD |
||
::boost::is_const<T>::value |
Tがトップレベルでconst修飾されている場合に真に評価する。 | 3.9.3 |
|||
::boost::is_volatile<T>::value |
Tがvolatile修飾されていれば真に評価する。 | 3.9.3 |
|||
::boost::is_POD<T>::value |
Tがconst/volatile修飾されたPOD型(訳註:Plane Old Data。非静的データメンバ、仮想関数、基本クラス、ユーザー定義コンストラクタ、コピーコンストラクタ、コピー代入演算子、およびデストラクタが含まれる)であれば真に評価する。 | 3.9p10 9p4 |
|||
::boost::has_trivial_constructor<T>::value |
Tが自明なデフォルトコンストラクタを持っている、すなわちT()がmemsetと同等であれば真。 | PC |
|||
::boost::has_trivial_copy<T>::value |
Tが自明なコピーコンストラクタを持っている、すなわちT(const T&)がmemcpyと同等であれば真。 | PC |
|||
::boost::has_trivial_assign<T>::value |
Tが自明な代入演算子を持っている、すなわちT::operator=(const T&)がmemcpyと同等であれば真。 | PC |
|||
::boost::has_trivial_destructor<T>::value |
Tが自明なデストラクタを持っている、すなわちT::~T()が効果なしであれば真。 | PC |
|||
::boost::is_stateless<T>::value |
Tが実体を持たない、要するにTが記憶領域を持たず、コンストラクタとデストラクタがトリビアルであれば真。 | PC |
|||
::boost::has_nothrow_constructor<T>::value |
Tが例外を発生させないデフォルトコンストラクタを持っていれば真。 | PC | |||
::boost::has_nothrow_copy<T>::value |
Tが例外を発生させないコピーコンストラクタを持っていれば真。 | PC | |||
::boost::has_nothrow_assign<T>::value |
Tが例外を発生させない代入演算子を持っていれば真。 | PC |
以下のテンプレートは2つの型の間に関連性があるかどうかを調べる。
Expression |
Description |
Reference |
Compiler requirements |
||
|
TとUが同じ型であれば真に評価する。 |
||||
::boost::is_convertible<T,U>::value |
型Tが型Uに変換できるのであれば真に評価する。 | 4 8.5 |
このテンプレートは、Borlandのコンパイラではコンストラクタベースの変換について、Metrowerksのコンパイラではすべての場合について、現時点では使用できないことに注意。 | ||
::boost::is_base_and_derived<T,U>::value |
型Tが型Uの基底クラスであれば真に評価する。 | 10 | P |
is_convertible
およびis_base_and_derived
では、変換があいまいな場合にはコンパイラがエラーを出すので注意すること。
struct A {}; struct B : A {}; struct C : A {}; struct D : B, C {}; bool const x = boost::is_base_and_derived<A,D>::value; // エラー bool const y = boost::is_convertible<D*,A*>::value; // エラー
以下のテンプレートは、ある型を別の型に、いくつかの明確な規則に基づいて変形する。各テンプレートにはテンプレート引数Tを変形した結果であるtypeという名のメンバがひとつだけ含まれている。
Expression |
Description |
Reference |
Compiler requirements |
||
::boost::remove_const<T>::type |
Tと同じ型であるが、トップレベルのconst修飾子を取り除いた型を作る。例えば、"const int"は"int"になるが、"const int*"は変化しないままとなる。 | 3.9.3 | P |
||
::boost::remove_volatile<T>::type |
Tと同じ型であるが、トップレベルのvolatile修飾子を取り除いた型を作る。例えば、"volatile int"は"int"になる。 | 3.9.3 |
P |
||
::boost::remove_cv<T>::type |
Tと同じ型であるが、トップレベルのconst/volatile修飾子を取り除いた型を作る。例えば、"const volatile int"は"int"になるが、"const int*"は変化せずそのままとなる。 | 3.9.3 | P |
||
::boost::remove_reference<T>::type |
Tが参照型であれば参照を取り除き、そうでなければTは変化せずそのままとなる。例えば、"int&"は"int"になるが、"int*"は変化しないままである。 | 8.3.2 | P |
||
::boost::remove_bounds<T>::type |
Tが配列型であればTからトップレベルの配列修飾子を取り除き、そうでなければTは変化せずそのままとなる。例えば、"int[2][3]"は"int[3]"になる。 | 8.3.4 | P |
||
::boost::remove_pointer<T>::type |
Tがポインタ型であればTから間接修飾を取り除き、そうでなければTは変化せずそのままとなる。例えば、"int*"は"int"になるが、"int&"は変化しないままである。 | 8.3.1 | P |
||
::boost::add_reference<T>::type |
Tが参照型であればTは変化せずそのままとなり、そうでなければTへの参照型に変換する。例えば、"int&"は変化せずにそのままであるが、"double"は"double&"になる。 | 8.3.2 | P |
||
::boost::add_pointer<T>::type |
"t"がTのインスタンスであるとき、add_pointer<T>::typeは"&t"が返す型である。例えば、"int"と"int&"はともに"int*"になる。 | 8.3.1 | P |
||
::boost::add_const<T>::type |
あらゆるTに対して"T const"と同じ。 | 3.9.3 | |||
::boost::add_volatile<T>::type |
あらゆるTに対して"T volatile"と同じ。 | 3.9.3 | |||
::boost::add_cv<T>::type |
あらゆるTに対して"T const volatile"と同じ。 | 3.9.3 |
上記の表が示すように、型変形テンプレートを正しく実装するには部分特殊化版のサポートが必要である。一方で、経験上この分類に属するテンプレートの多くは非常に有益であり、ジェネリックライブラリの実装においてしばしば必須となる。 これらのテンプレートが不足していると、それらのライブラリを部分特殊化版の言語仕様をまだサポートしていないコンパイラに移植する上で大きな制約要因となる。 そうしたコンパイラの中にはしばらく部分特殊化版をサポートしないものがあり、少なくともそのうちの1つは非常に広く普及しているため、ライブラリでは移植を実現させるための回避手段を提供することにした。 回避手段を裏付ける基本的なアイデアは以下の通り。
最初の内容はこのようなものであり、コンパイルに成功することが保証されている。
BOOST_STATIC_ASSERT((is_same<char, remove_reference<char&>::type>::value));
BOOST_STATIC_ASSERT((is_same<char const, remove_reference<char const&>::type>::value));
BOOST_STATIC_ASSERT((is_same<char volatile, remove_reference<char volatile&>::type>::value));
BOOST_STATIC_ASSERT((is_same<char const volatile, remove_reference<char const volatile&>::type>::value));
BOOST_STATIC_ASSERT((is_same<char*, remove_reference<char*&>::type>::value));
BOOST_STATIC_ASSERT((is_same<char const*, remove_reference<char const*&>::type>::value));
...
BOOST_STATIC_ASSERT((is_same<char const volatile* const volatile* const volatile, remove_reference<char const volatile* const volatile* const volatile&>::type>::value));
そして次の内容は'char'、'int'や他の組み込み型だけでなく、独自に定義された型に対しても上記のコードを働かせるための仕組みをライブラリのユーザに提供する。
struct my {};
BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(my)
BOOST_STATIC_ASSERT((is_same<my, remove_reference<my&>::type>::value));
BOOST_STATIC_ASSERT((is_same<my, remove_const<my const>::type>::value));
// etc.
部分特殊化版がサポートされないコンパイラでは、BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATIONは中身のないマクロとして評価されることに注意。
以下のテンプレートは要求した特徴を持った型を作り出す。
Expression |
Description |
Reference |
Compiler requirements |
||
::boost::type_with_alignment<Align>::type |
Alignの倍数に整列された組み込み型またはPOD型を見つける。 |
::boost::function_traits
クラステンプレートは関数型から情報を取り出す。
Expression |
Description |
Reference |
Compiler requirements |
||
::boost::function_traits<F>::arity |
関数型Fの引数の数を調べる。 | 部分特殊化版がサポートされない場合、このテンプレートは参照型についてはコンパイルできない。 | |||
::boost::function_traits<F>::result_type |
関数型Fが返す型。 | P | |||
::boost::function_traits<F>::argN_type |
関数型Fの第N(1≦N≦Fの引数の数)引数の型。 | P |
上の表中にある記号の意味は以下の通り。
P |
クラスが正しく働くためにはクラステンプレートの部分特殊化版のサポートを必要としていることを示す。 |
C |
その特性クラスのためにコンパイラの直接的なサポートが必要であることを示す。 |
D |
特性クラスがコンパイラの直接的なサポートを必要とするクラスに依存していることを示す。 |
DやCの印が付いたクラスに対して、コンパイラのサポートが受けられなければ、この型特性は実際には"真"が正しい場合に"偽"を返すことがある。この規則の唯一の例外は"is_class"で、Tが本当にクラスかどうかの推量を試みるにあたって、実際には"偽"が正しい場合に"真"を返すことがある。 こうしたことが起こるのは、Tが共用体あるいはコンパイラ独自のスカラ型(それらの型特性が特化されていない)の場合である。
コンパイラがサポートしていない場合、これらの特性が常に正しい値を返すことを保証するには、ユーザ定義のそれぞれの共用体型に対して'is_union'を、ユーザ定義のそれぞれの空の複合型に対して'is_empty'を、そしてユーザ定義のそれぞれのPOD型に対して'is_POD'を特化しなければならない。ユーザ定義型が'has_*'特性を持っておりPODではない場合には、'has_*'特性もまた特化すべきである。
以下の規則が自動的に当てはまる。
is_enumはis_PODでもある。
is_PODはhas_*でもある。
これが意味するのは、例えば、空のPOD構造体がある場合には、is_emptyとis_PODを特化し、すべてのhas_*が真を返すようにするということである。
型特性ライブラリは通常下記をインクルードする。
#include <boost/type_traits.hpp>
とはいえ、ライブラリは実際にはいくつかのより小さいヘッダに分かれており、ときには実際に必要な型特性クラスを得るためにその中のひとつを直接インクルードする方が便利なことがある。しかし型特性クラスは相互依存性が高いことに注意すること。したがって、この方法は意外に節減にはならないかもしれない。以下の表では型特性クラスをアルファベット順に、各テンプレートが収められたヘッダとともに並べる。
Template class | Header | ||
add_const |
<boost/type_traits/transform_traits.hpp> |
||
add_const |
<boost/type_traits/transform_traits.hpp> |
||
add_pointer |
<boost/type_traits/transform_traits.hpp> |
||
add_reference |
<boost/type_traits/transform_traits.hpp> |
||
add_volatile |
<boost/type_traits/transform_traits.hpp> |
||
alignment_of |
<boost/type_traits/alignment_traits.hpp> |
||
has_trivial_assign |
<boost/type_traits/object_traits.hpp> |
||
function_traits |
<boost/type_traits/function_traits.hpp> |
||
has_trivial_constructor |
<boost/type_traits/object_traits.hpp> |
||
has_trivial_copy |
<boost/type_traits/object_traits.hpp> |
||
has_trivial_destructor |
<boost/type_traits/object_traits.hpp> |
||
is_arithmetic |
<boost/type_traits/arithmetic_traits.hpp> |
||
is_array
|
<boost/type_traits/composite_traits.hpp> |
||
is_base_and_derived |
<boost/type_traits/object_traits.hpp> |
||
is_class |
<boost/type_traits/object_traits.hpp> |
||
is_compound |
<boost/type_traits/object_traits.hpp> |
||
is_const |
<boost/type_traits/cv_traits.hpp> |
||
is_convertible |
<boost/type_traits/conversion_traits.hpp> |
||
is_empty |
<boost/type_traits/object_traits.hpp> |
||
is_enum |
<boost/type_traits/composite_traits.hpp> |
||
is_float |
<boost/type_traits/arithmetic_traits.hpp> |
||
is_function |
<boost/type_traits/function_traits.hpp> |
||
is_fundamental |
<boost/type_traits/arithmetic_traits.hpp> |
||
is_integral |
<boost/type_traits/arithmetic_traits.hpp> |
||
is_member_pointer |
<boost/type_traits/composite_traits.hpp> |
||
is_member_function_pointer |
<boost/type_traits/composite_traits.hpp> |
||
is_object
|
<boost/type_traits/object_traits.hpp> |
||
is_POD |
<boost/type_traits/object_traits.hpp> |
||
is_pointer |
<boost/type_traits/composite_traits.hpp> |
||
is_reference |
<boost/type_traits/composite_traits.hpp> |
||
is_same |
<boost/type_traits/same_traits.hpp> |
||
is_scalar |
<boost/type_traits/object_traits.hpp> |
||
is_union |
<boost/type_traits/composite_traits.hpp> |
||
is_void |
<boost/type_traits/arithmetic_traits.hpp> |
||
is_volatile |
<boost/type_traits/cv_traits.hpp> |
||
remove_bounds |
<boost/type_traits/transform_traits.hpp> |
||
remove_const |
<boost/type_traits/cv_traits.hpp> |
||
remove_cv |
<boost/type_traits/cv_traits.hpp> |
||
remove_pointer |
<boost/type_traits/transform_traits.hpp> |
||
remove_reference
|
<boost/type_traits/transform_traits.hpp> |
||
remove_volatile |
<boost/type_traits/cv_traits.hpp> |
||
type_with_alignment |
<boost/type_traits/alignment_traits.hpp> |
型特性テンプレートを使用できるいくつかの方法を説明したプログラム例が4つある。
std::copyのコピー操作を最適化するために適宜memcpyを使用するバージョンを示す。
// // opt::copy // std::copyと同じセマンティクス // 適宜memcpyを呼び出す。 // namespace detail{ template<typename I1, typename I2> I2 copy_imp(I1 first, I1 last, I2 out) { while(first != last) { *out = *first; ++out; ++first; } return out; } template <bool b> struct copier { template<typename I1, typename I2> static I2 do_copy(I1 first, I1 last, I2 out) { return copy_imp(first, last, out); } }; template <> struct copier<true> { template<typename I1, typename I2> static I2* do_copy(I1* first, I1* last, I2* out) { memcpy(out, first, (last-first)*sizeof(I2)); return out+(last-first); } }; } template<typename I1, typename I2> inline I2 copy(I1 first, I1 last, I2 out) { typedef typename boost::remove_cv<typename std::iterator_traits<I1>::value_type>::type v1_t; typedef typename boost::remove_cv<typename std::iterator_traits<I2>::value_type>::type v2_t; return detail::copier< ::boost::type_traits::ice_and< ::boost::is_same<v1_t, v2_t>::value, ::boost::is_pointer<I1>::value, ::boost::is_pointer<I2>::value, ::boost::has_trivial_assign<v1_t>::value >::value>::do_copy(first, last, out); }
std::fillの充填操作を最適化するために適宜memsetを使用するバージョンを示す。 また、エイリアシング問題を避けるため、引数の受け渡しを最適化するためにcall_traitsを使用する。
namespace opt{ // // fill // std::fillと同じ。引数の受け渡しの"最適化"のために // call_traitsとともに適宜memsetを使用する。 // // namespace detail{ template <typename I, typename T> void do_fill_(I first, I last, typename boost::call_traits<T>::param_type val) { while(first != last) { *first = val; ++first; } } template <bool opt> struct filler { template <typename I, typename T> struct rebind { static void do_fill(I first, I last, typename boost::call_traits<T>::param_type val) { do_fill_<I,T>(first, last, val); } }; }; template <> struct filler<true> { template <typename I, typename T> struct rebind { static void do_fill(I first, I last, T val) { std::memset(first, val, last-first); } }; }; } template <class I, class T> inline void fill(I first, I last, const T& val) { typedef detail::filler< ::boost::type_traits::ice_and< ::boost::is_pointer<I>::value, ::boost::is_arithmetic<T>::value, (sizeof(T) == 1) >::value> filler_t; typedef typename filler_t:: template rebind<I,T> binder; binder::do_fill(first, last, val); } }; // namespace opt
std::iter_swapの正規のものと同様の代替イテレータとともに動作するバージョンを示す。それは、正規のイテレータに対してstd::swapを呼び出すか、あるいは"遅いけれども安全"なswapを呼び出す。
namespace opt{ // // iter_swap: // イテレータが代替イテレータかどうかを調べ、 // それに応じて最適な形式を使う。 // namespace detail{ template <bool b> struct swapper { template <typename I> static void do_swap(I one, I two) { typedef typename std::iterator_traits<I>::value_type v_t; v_t v = *one; *one = *two; *two = v; } }; template <> struct swapper<true> { template <typename I> static void do_swap(I one, I two) { using std::swap; swap(*one, *two); } }; } template <typename I1, typename I2> inline void iter_swap(I1 one, I2 two) { typedef typename std::iterator_traits<I1>::reference r1_t; typedef typename std::iterator_traits<I2>::reference r2_t; detail::swapper< ::boost::type_traits::ice_and< ::boost::is_reference<r1_t>::value, ::boost::is_reference<r2_t>::value, ::boost::is_same<r1_t, r2_t>::value >::value>::do_swap(one, two); } }; // namespace opt
このアルゴリズムはstd::uninitialized_copyの逆である。初期化済みのメモリブロックを受け取り、その中のすべてのオブジェクトに対してデストラクタを呼び出す。これは一般には自分自身でメモリ管理を行うコンテナクラスの内部で使われる。
namespace opt{ // // アルゴリズムdestroy_array: // std::unitialized_copyの逆で、初期化済みのメモリブロックを受け取り、 // その中の全オブジェクトに対してデストラクタを呼び出す。 // namespace detail{ template <bool> struct array_destroyer { template <class T> static void destroy_array(T* i, T* j){ do_destroy_array(i, j); } }; template <> struct array_destroyer<true> { template <class T> static void destroy_array(T*, T*){} }; template <class T> void do_destroy_array(T* first, T* last) { while(first != last) { first->~T(); ++first; } } }; // namespace detail template <class T> inline void destroy_array(T* p1, T* p2) { detail::array_destroyer<boost::has_trivial_destructor<T>::value>::destroy_array(p1, p2); } } // namespace opt
Revised 22 April 2001
Documentation © Copyright John Maddock 2001. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose.
The type traits library is based on contributions by Steve Cleary, Beman Dawes, Aleksey Gurtovoy, Howard Hinnant, Jesse Jones, Mat Marcus, John Maddock and Jeremy Siek.
Mat Marcus and Jesse Jones have worked on, and published a paper describing the partial specialisation workarounds used in this library.
The is_convertible template is based on code originally devised by Andrei Alexandrescu, see "Generic<Programming>: Mappings between Types and Values".
Maintained by John Maddock, the latest version of this file can be found at www.boost.org, and the boost discussion list at www.yahoogroups.com/list/boost.
Japanese Translation Copyright © 2003 Takagi,Yusei
オリジナルの、及びこの著作権表示が全ての複製の中に現れる限り、この文書の複製、利用、変更、販売そして配布を認める。このドキュメントは「あるがまま」に提供されており、いかなる明示的、暗黙的保証も行わない。また、いかなる目的に対しても、その利用が適していることを関知しない。