由于C++不支持type_of,所以Traits技术,实际上就是通过通过模板中的类型推导机制,获取到变量的类型,以其在编译器确定函数的调用。STL中的迭代器就广泛的运用到该技术。下面是一个简单的例子:
凡是一个迭代器,我们总是希望能够知道它所指的数据的数据类型,我们可以这样做:
template <class T> class Iterator { public: typedef typename T::value_type value_type; // ... };
当然,这需要我们用到迭代器的类,定义一个value_type,否则会编译不过。
然后,无论我们在什么地方用到迭代器,我们总是可以知道它所指的数据类型:
Iterator::value_type value;
但是这样的写法有一个缺陷,就是:指针也是一种迭代器,但是却不是类,因此我们便无法得知指针指向的是什么元素。为此引入Traits技术,在原来的迭代器类上面再加一层:
template <class Iter> class Iterator_Traits { public: typedef typename Iter::value_type value_type; };
这样,我们就可以得知一个迭代器所指的类型:
Iterator_Traits<Iterator>::value_type value;
而对于指针,可以使用模板中的偏特化技术:
template <class T> class Iterator_Traits<T *> { public: typedef T value_type; }; template <class T> class Iterator_Traits<const T *> { public: typedef T value_type; };
因此,模板编程中的Traits技术,其实就是“萃取”出变量类型。
还可以写一个辅助函数:
template <class Iter> Iterator_Traits<Iter> value_type(Iter iter) { return static<Iterator_Traits<Iter>::value_type*>(0); }
这样,我们在写程序的时候,可以把程序写成两层:
// 第一层 template <class Iter> void Function(Iter I) { _Function(I, value_type(I)); } // 第二层: 根据不同的数据类型,做不同的处理 template <class Iter> void _Function(Iter I, int) { // .... } template <class Iter> void _Function(Iter I, char) { // .... }