STL — type_traits


本文原创

traits 是用于在编译期进行特性提取的技术,type_traits 在 STL 中用于判定模板形参类型,以此针对不同类型执行不同的实现。

type_traits.h 文件注释中就提供了一个例子说明其用途:

// Copy an array of elements which have non-trivial copy constructors
template <class T> void copy(T* source, T* destination, int n, __false_type);
// Copy an array of elements which have trivial copy constructors. Use memcpy.
template <class T> void copy(T* source, T* destination, int n, __true_type);
// Copy an array of any type by using the most efficient copy mechanism
template <class T> inline void copy(T* source, T* destination, int n)
{
   copy(source, destination, n, typename __type_traits<T>::has_trivial_copy_constructor());
}

最下面一个 copy 是对外被调用的,利用 __type_traits 判定类型 T 是否有默认的拷贝构造函数,根据判定结果选择调用上面两个 copy 中的一个,以此针对某些类型提供高效的特殊实现。

__true_type 和 __false_type 都是一个空的结构体,先来看看 __type_traits 的一般模板:

struct __true_type
{
};

struct __false_type
{
};

template <class _Tp>
struct __type_traits
{ 
    typedef __true_type    this_dummy_member_must_be_first; /* Do not remove this member. It informs a compiler which automatically specializes __type_traits that this __type_traits template is special. It just makes sure that things work if an implementation is using a template called __type_traits for something unrelated. */

    /* The following restrictions should be observed for the sake of
       compilers which automatically produce type specific specializations 
       of this class:
          - You may reorder the members below if you wish
          - You may remove any of the members below if you wish
          - You must not rename members without making the corresponding
            name change in the compiler
          - Members you add will be treated like regular members unless
            you add the appropriate support in the compiler. */
    typedef __false_type    has_trivial_default_constructor;
    typedef __false_type    has_trivial_copy_constructor;
    typedef __false_type    has_trivial_assignment_operator;
    typedef __false_type    has_trivial_destructor;
    typedef __false_type    is_POD_type;
};

关于 POD 类型,解释如下:

A type that consists of nothing but Plain Old Data. A POD type is a C++ type that has an equivalent in C, and that uses the same rules as C uses for initialization, copying, layout, and addressing.

“An aggregate is an array or class with no user-declared constructors, no private or protected non-static data members, no base classes and no virtual functions.”

“A POD-struct is an aggregate class that has no non-static data members of type non-POD-struct, non-POD-union (or array of such types) or reference, and has no user-define copy operator and no user-defined destructor.”

一般模板默认类型无 trivial constructor 和 trivial destructor 等,也不是 POD 类型。这里的 trivial constructor 表示无用户自定义的构造函数,由编译器生成默认的构造函数,而且该类无虚基类,类中无虚函数。

随后,针对各种内置类型对模板做了全局特化,包括 bool, char, unsigned char, short, unsigned short, int, unsigned int, wchar_t, long, unsigned long, long long, unsigned long long, float, double, long double,形式都一样:

template <>
struct __type_traits<bool>
{
    typedef __true_type    has_trivial_default_constructor;
    typedef __true_type    has_trivial_copy_constructor;
    typedef __true_type    has_trivial_assignment_operator;
    typedef __true_type    has_trivial_destructor;
    typedef __true_type    is_POD_type;
};

此外,若是声明了宏 __STL_CLASS_PARTIAL_SPECIALIZATION,则还对指针类型作了局部特化:

#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
template <class _Tp>
struct __type_traits<_Tp*>
{
    typedef __true_type    has_trivial_default_constructor;
    typedef __true_type    has_trivial_copy_constructor;
    typedef __true_type    has_trivial_assignment_operator;
    typedef __true_type    has_trivial_destructor;
    typedef __true_type    is_POD_type;
};
#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */
    ......
#endif

如果没声明该宏,则上述 …… 处对类型 char *, unsigned char *, const char *, const unsigned char * 做了和其他内置类型同样的全局特化。

type_traits.h 文件中还有一个判断类型是不是整型或可转换为整型的 _Is_integer 的模板,一般模板置否:

template <class _Tp>
struct _Is_integer
{
  typedef __false_type _Integral;
};

对于可转换为整型的类型 bool, char, unsigned char, short, unsigned short, int, unsigned int, wchar_t, long, unsigned long, long long, unsigned long long,作类似以下的全局特化:

template <>
struct _Is_integer<bool>
{
  typedef __true_type _Integral;
};

Leave a comment

邮箱地址不会被公开。 必填项已用*标注