Vc8 的 type_traits 关键字 zz.

VC8 的 type_traits 关键字

引言
 
type traits 用来在编译期间获取类型的信息,在 boost 库中用了很多诡异的方法来检测,主要是模板特化机制,比如两个类型是否一直:
 
template <typename T1, typename T2>
struct is_same
{
    static const bool value = false;
};
template <typename T>
struct is_same<T, T>
{
    static const bool value = true;
};
 
一个普通版本的模板,一个特化的,就可以区分传入的类型是否一致:
int*p = is_same<int, long>::value; // 编译成功,因为false是有效的空指针常量
int*p = is_same<int, int>::value; // 编译错误,因为true不是指针。
如果要实现检测是否是整数呢?
template <typename T>
struct is_integral
{
    static const bool value = false;
};
 
template <> struct is_integral <bool>{   static const bool value = true; };
template <> struct is_integral <char>{   static const bool value = true; };
template <> struct is_integral <wchar_t>{   static const bool value = true; };
template <> struct is_integral <signed char>{   static const bool value = true; };
template <> struct is_integral <unsigned char>{   static const bool value = true; };
template <> struct is_integral <short>{   static const bool value = true; };
template <> struct is_integral <unsigned short>{   static const bool value = true; };
template <> struct is_integral <int>{   static const bool value = true; };
template <> struct is_integral <unsigned int>{   static const bool value = true; };
template <> struct is_integral <long>{   static const bool value = true; };
template <> struct is_integral <unsigned long>{   static const bool value = true; };
...
 
发现还遗漏了一点,就是类型加上 cv 限制后跟原来的类型不一致,那么 is_interal<const int>::value 就不再为真,所以,要修正这个bug,还需要特化:
template <> struct is_integral <const int>{   static const bool value = true; };
template <> struct is_integral <volatile int>{   static const bool value = true; };
template <> struct is_integral <const volatile int>{   static const bool value = true; };
好吧,那先把上面的在扩大三倍再说吧。
 
这些都比较容易实现,复杂的就需要根据一些规则来推算,如果不是这个,又不是那个,又不是……,那么就是某物,比如判断是否是自定义的类类型:
不是内置类型
不是数组
不是指针
不是引用
不是函数
不是函数指针
不是成员函数
不是成员函数指针
那么一定是类类型。
 
麻烦吗?更麻烦的还有呢。
 
比如如何判断是不是 enum,是不是 union?办法有,不过是越来越复杂。
 
再比如如何判断是不是 POD 类型,尤其是判断 POD 类型,对模板库的性能有较大帮助,因为 POD 类型可以直接用
memcpy 搬移,不需要构造和析构。很遗憾,有些用上面的规则无法推出。
 
其实这些信息就在编译器内部,与其偷偷摸摸地检测,这样不但慢而且容易出错,不如直接问编译器要,据说 sgi 的编译器老早就实现了一些编译器内置的 type traits 支持,
现在好消息来了,VC 2005 也支持了:
 
不过 VC 2005 也只支持了一些用模板特化机制难以检测,列表如下:
__has_assign( type )
__has_copy( type )
__has_finalizer( type )
__has_nothrow_assign( type )
__has_nothrow_constructor( type )
__has_nothrow_copy( type )
__has_trivial_assign( type )
__has_trivial_constructor( type )
__has_trivial_copy( type )
__has_trivial_destructor( type )
__has_user_destructor( type )
__has_virtual_destructor( type )
__is_abstract( type )
__is_base_of( base , derived)
__is_class( type )
__is_convertible_to( from , to )
__is_delegate( type )
__is_empty( type )
__is_enum( type )
__is_interface_class( type )
__is_pod( type )
__is_polymorphic( type )
__is_ref_array( type )
__is_ref_class( type )
__is_sealed( type )
__is_simple_value_class( type )
__is_union( type )
__is_value_class( type )
特别感谢 ctrlz@newsmth 提供信息,VC 2005 发布快两年了,还没把它的扩展语法都看一遍,真是惭愧。
 

Powered by Jekyll and Theme by solid

本站总访问量