STL源码学习系列三: 编程技法(Traits)

编程技法(Traits)


前言

Traits编程技术是STL中最重要的编程技术,Traits可以获取一个类型的相关信息。

在C/C++中可以使用sizeof()来获取变量的大小,但是如果想获取变量的类型,却没有typeof()这样的函数,而Traits编程技法就是为了实现typeof()的功能,这种功能主要可以用于迭代器相应型别的设计上。


Traits编程

Traits可以获取一个类型的相关信息,首先我们看下面的程序:

template <class T, class type>  
void function(T t, type u) 
{  
    type temp;   
    // ... The rest work of function…  
}

在上面的程序中,我们怎么样才能获得已声明变量temp的类型type呢???


函数模板的参数推导机制

在模板中,模板参数推导机制可以解决这个问题,在下面程序中编译器直到变量temp的类型为int:

template <class T, class type>  
void function(T iter, type u)   
{  
    type temp; // 通过模板参数推导获得temp变量的类型  
    ....  
}  
template <class T>  
void func(T iter)   
{  
    function(iter, *iter);   
}  

int main()  
{  
    int i = 12;  
    func(&i)  
}

这里利用函数模板的参数推导机制通过&i推断出func的模板参数I是一个int类型的指针,再通过I类型变量iter和其取内容iter获取到int和int类型。
上面介绍的是获得局部变量的类型,这个可以通过模板参数推导机制完成。

如果我们要获得函数返回值的类型时,该怎么处理呢???


内嵌型别的函数模板

这个问题针对不同类型有不同的方法可以解决,类型型别:用户自定义类型(如结构体,类)和内置类型(如整型,原生指针等)。

用户自定义类型的函数返回值类型,我们可以使用内嵌型别技术就可以知道返回值的类型。
设计思路如下:

template<class T>
struct MyIter
{
    typedef T value_type; //内嵌型别声明
};

作为函数返回值时的写法为:

template <class I>
typename I::value_type/ /函数返回类型
func(I ite)
{
    return *iter;
}

int main()
{
    //使用func
    MyIter<int> ite(new int(8));
    func(ite);
}

使用的时候,通过func模板函数的参数推断出 ite的类型I,接着使用之前定义的内嵌型别声明。这种方式的缺陷就是管不了原生指针,例如int*,它不存在内嵌类型。

若不是用户自定义的类型,而是内置类型时,例如是原生指针,因为原生指针不能内嵌型别声明,所以内嵌型别在这里不适用。这时候该怎么处理呢?? ?


偏特化

为模板的某个参数进行特化工作,也就是为泛化的设计提供特化的版本,这样我们就利用偏特化的特性为(T^和const T*) 这种原生指针和const 指针设计特化版本:

template <class T>
struct iterator_traits<T*> //为原生指针设计的特化版本
{
    typedef T value_type;
};

template <class T>
struct iterator_traits<const T*> //为const 指针设计的特化版本
{
    typedef T value_type;
};

我们之所以要萃取(Traits)迭代器相关的类型,就是要把迭代器相关的类型用于声明局部变量、用作函数的返回值等一系列行为。对于原生指针和point-to-const类型的指针,采用模板偏特化技术对其进行特殊处理。要使用Traits功能,则必须自行以内嵌型别定义的方式定义出相应型别。

我们上面讲解的只是迭代器其中一种类型value type,在迭代器中还有其他类型:

    template <class _Iterator>  
    struct iterator_traits 
    {  
      typedef typename _Iterator::iterator_category  iterator_category; //迭代器类型  
      typedef typename _Iterator::value_type         value_type;        //迭代器所指对象的类型  
      typedef typename _Iterator::difference_type    difference_type;   //迭代器之间距离  
      typedef typename _Iterator::pointer            pointer;           //迭代器所指之物  
      typedef typename _Iterator::reference          reference;         //迭代器引用之物  
    };  

End

猜你喜欢

转载自blog.csdn.net/qq_34777600/article/details/80425381