一番基本的な使い方です。 例えば、こんな関数オブジェクトがあったとして、
template <typename T_> struct FuncAdaptor { void operator() (); };
このクラス、関数アダプタだとして、T_ は関数でないといけないとします。 つまり FuncAdaptor<int> などとされると困るのです。
まあ、どうせコンパイルエラーになるでしょうし、 ほっといてもいいですし、コメントでその旨伝えても良いのですが、 どうせなら早い内にエラーになってもらいたいのです。
そういう時は type_traits の type categorisation が役に立ちます。 is_pointer, is_void などと、 コンパイルタイムで型を調べることができるのです。 例えばこの場合、
template <typename T_> struct FuncAdaptor { BOOST_STATIC_ASSERT( boost::is_pointer<T_>::value || boost::is_class<T_>::value || boost::is_function<T_>::value ); void operator() (); };
として、クラスの頭にチェックする文を加えます。 まあ、このチェックはかなり不十分ですが、 FuncAdaptor<int> のような論外な誤用には対応できます。
こうすることによって、このコードのユーザに、 意味不明なエラーメッセージでは無く、 テンプレート引数が不適切であることを明確に伝えることができます。
is_ 系のものは、他にも is_const、 has_trivial_constructor など 便利そうなものが揃っています。
また、型の関係を調べる、 is_same, is_base_and_derived などもあります。
Eiffel の DBC をライブラリとして実装した感じですね。 しかも超強力。さすがマルチパラダイム言語。
この項では BOOST_STATIC_ASSERT との組み合わせしか紹介していませんが、 次項の MPL と組み合わせるとさらに面白いことになります。
まあ、こんなクラスがあったとして、
template <typename T_> class Class { public: explicit Class(T_ val) : val_(val) {} T_ getPlusOne() { return val_+1; } private: T_ val_; };
Class<int> なんて作って使っている内は問題無かったのですが、 Class<int&> などとして、getPlusOne を呼びだすとコンパイルエラー。 val_+1 は一時オブジェクトだから、その参照は返しちゃならんのです。 T_ が参照の時は、T_ から参照を取り払ったものを getPlusOne の返り値にしたいのです。
んな時は、remove_reference が役に立ちます。 getPlusOne の行を
boost::remove_reference<T_>::type getPlusOne() { return val_+1; }
とすることによって、参照なら、参照を取り払ったものが、 この戻り値にうまくなってくれます。
型変換のためのものは、他にも remove_const など、きちんと揃っているので、 必要に応じて使い分けて下さい。
私が書かなかった copy 関係が K.INABA氏によって 補填 されています。
全てリンクフリーです。 コード片は自由に使用していただいて構いません。 その他のものはGPL扱いであればあらゆる使用に関して文句は言いません。 なにかあれば下記メールアドレスへ。