メタ関数1

  • コンパイル時に、型・定数を引数として受け取り、それを加工して型・定数を返すclass template。typedef・enum・static constで戻り値を返す。

基本形は以下の通り。

//argを引数として受け取り、そのままtypeとして返すメタ関数
template< typename arg >
struct func
{
    typedef arg type;
};

型を返す場合はtypedef ... type、値を返す場合はtypedef ... valueとするのが一般的なようです。


単純な使い方。
intを渡すとintがそのまま返ってきます。

func< int >::type a = 1; //int a = 1;

is_void

  • 指定した型がvoidかどうか調べる
//デフォルトはfalse
template< typename T >
struct is_void
{
    static const bool value = false;
};

//voidはtrueで特殊化
template<>
struct is_void< void >
{
    static const bool value = true;
};

特殊化を使うことで、コンパイル時の条件分岐が可能です。

  • 使い方
    if( is_void< int >::value )   //if( false )
        cout << "voidでない" << endl;
    else
        cout << "void" << endl;

is_float

  • 指定した型が実数型かどうか
//デフォルトはfalse
template< typename T >
struct is_float
{
    static const bool value = false;
};

//floatはtrueで特殊化
template<>
struct is_float< float >
{
    static const bool value = true;
};

//doubleはtrueで特殊化
template<>
struct is_float< double >
{
    static const bool value = true;
};

同じ書式が並んで面倒ですね。is_系のメタ関数はboolで結果を返すので、基底にbool_traitsを用意しましょうか。

bool_traits

template< bool val >
struct bool_traits;

template<>
struct bool_traits< true >
{
    typedef bool value_t;
    static const value_t value = true;
};
template<>
struct bool_traits< false >
{
    typedef bool value_t;
    static const value_t value = false;
};
typedef bool_traits< true > true_;
typedef bool_traits< false > false_;

bool_traits継承版

//指定した型がvoidかどうか
template< typename T >
struct is_void : false_{};

template<>
struct is_void< void > : true_{};


//指定した型が実数型かどうか
template< typename T >
struct is_float : false_{};

template<>
struct is_float< float > : true_{};

template<>
struct is_float< double > : true_{};

よく見ると、デフォルトの基本形定義と、型を指定した特殊化バージョンの2つ。マクロを使うと楽できそうです。

マクロ版

#define bool_traits_def( name, value )    \
    template< typename T >                \
    struct name : value##_{};

#define bool_traits_spec( name, type, value ) \
    template<>                                \
    struct name< type > : value##_{};
//指定した型がvoidかどうか
bool_traits_def( is_void, false );
bool_traits_spec( is_void, void, true );

//指定した型が実数型かどうか
bool_traits_def( is_float, false );
bool_traits_spec( is_float, float, true );
bool_traits_spec( is_float, double, true );