Type Traits

Boostのソースを解析してType Traitsを作成中


労を惜しまずに作ればこうなる

template <typename Type>
struct is_void {
    enum { value = 0 };
};

template <>
struct is_void<void> {
    enum { value = 1 };
};

でもめんどくさいので

こういう簡単に特殊化できるようにするマクロを作って

template <typename Type, Type Value>
struct integral_constant {
    static const Type value = Value;
    typedef Type value_type;
};

typedef integral_constant<bool, true>  true_type;
typedef integral_constant<bool, false> false_type;

// 指定された型を特殊化
#define SHAND_TRAITS_SPEC0(Spec, Value) \
    template <> \
    struct Spec : public integral_constant<bool, Value> {};

#define SHAND_TRAITS_SPEC1(Spec, Value) \
    template <typename Type> \
    struct Spec : public integral_constant<bool, Value> {};

#define SHAND_TRAITS_SPEC2(Spec, Value) \
    template <typename Type, typename ClassName> \
    struct Spec : public integral_constant<bool, Value> {};

// Type, Type const, Type volatile, Type const volatileの4つを一気に特殊化
#define SHAND_TRAITS_SPEC(Order, Traits, SpecialType, Value)              \
	SHAND_TRAITS_SPEC##Order##(Traits<SpecialType>,                Value) \
	SHAND_TRAITS_SPEC##Order##(Traits<SpecialType const>,          Value) \
	SHAND_TRAITS_SPEC##Order##(Traits<SpecialType volatile>,       Value) \
	SHAND_TRAITS_SPEC##Order##(Traits<SpecialType const volatile>, Value)

こう使う

// is_void : void型
template <typename Type>
struct is_void : public false_type {};
SHAND_TRAITS_SPEC(0, is_void, void, true)


// is_integral : 整数型
template <typename Type>
struct is_integral : public false_type {};
SHAND_TRAITS_SPEC(0, is_integral, bool,               true)
SHAND_TRAITS_SPEC(0, is_integral, char,               true)
SHAND_TRAITS_SPEC(0, is_integral, signed char,        true)
SHAND_TRAITS_SPEC(0, is_integral, unsigned char,      true)
SHAND_TRAITS_SPEC(0, is_integral, wchar_t,            true)
SHAND_TRAITS_SPEC(0, is_integral, short,              true)
SHAND_TRAITS_SPEC(0, is_integral, unsigned short,     true)
SHAND_TRAITS_SPEC(0, is_integral, int,                true)
SHAND_TRAITS_SPEC(0, is_integral, unsigned int,       true)
SHAND_TRAITS_SPEC(0, is_integral, long,               true)
SHAND_TRAITS_SPEC(0, is_integral, unsigned long,      true)
SHAND_TRAITS_SPEC(0, is_integral, long long,          true)
SHAND_TRAITS_SPEC(0, is_integral, unsigned long long, true)

// is_float : 浮動小数点型
template <typename Type>
struct is_float : public false_type {};
SHAND_TRAITS_SPEC(0, is_float, float,       true)
SHAND_TRAITS_SPEC(0, is_float, double,      true)
SHAND_TRAITS_SPEC(0, is_float, long double, true)
// is_reference : 参照型
template <typename Type>
struct is_reference : public false_type {};

template <typename Type>
struct is_reference<Type&> : public true_type {};

// is_pointer : ポインタ型
template <typename Type>
struct is_pointer : false_type {};
SHAND_TRAITS_SPEC(1, is_pointer, Type*, true)


マクロは忘れずに消しましょう

#undef SHAND_TRAITS_SPEC0
#undef SHAND_TRAITS_SPEC1
#undef SHAND_TRAITS_SPEC2
#undef SHAND_TRAITS_SPEC


サンプル

#include <iostream>
#include <shand/type_traits.hpp>

using namespace std;
using namespace shand;

int main()
{
    // intが整数だったら1、整数じゃなかったら0
    cout << is_integral<int>::value << endl;
    return 0;
}

そしてさらにめんどくさいのでVC++6.0には非対応


Boostはとても勉強になります


参考サイト
Boost - Type Traits(型特性)