boost user - type_traits

since: 2002-08-29 update: 2002-08-29 count:

サンプルコード

この型は何者?

一番基本的な使い方です。 例えば、こんな関数オブジェクトがあったとして、

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氏によって 補填 されています。


home / index

全てリンクフリーです。 コード片は自由に使用していただいて構いません。 その他のものはGPL扱いであればあらゆる使用に関して文句は言いません。 なにかあれば下記メールアドレスへ。

shinichiro.hamaji _at_ gmail.com / shinichiro.h