STL之traits编程技法

Posted vlyf

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STL之traits编程技法相关的知识,希望对你有一定的参考价值。

摘要

主要讨论如何获取迭代器相应型别。使用迭代器时,很可能用到其型别,若需要声明某个迭代器所指对象的型别的变量,该如何解决。方法如下:

function template的参数推导机制

例如:

template<typename I, typename T>
void func_impl(I iter, T t)
{
    //T为迭代器所指对象的型别
    T tmp;
    //.....
}

template<typename I>
inline
void func(I iter)
{   
    //func工作交给func_impl完成
    func_impl(iter, *iter);
}

int main()
{
    int i;
    func(&i);

    return 0;
}

func_impl()是一个 function template,一旦被调用,编译器会自动进行template参数推导,从而导出型别T,无需自己指出型别,解决问题。迭代器相应型别不只是迭代器所指对象的型别一种而已,最常用的相应型别有五种,但并非任何情况都可利用上述template参数推导机制来取得。这就需要其他方法。

Traits编程技法

迭代器所指对象的型别,成为该迭代器的value type,上述模板参数推导并非全面可用,在需要value type作为函数返回值时,就不能解决了。template参数推导的只是参数而已。因此,声明内嵌型别就出现了。

例如:

template<typename T>
struct MyIter
{
    typedef T value_type;   //内嵌型别声明
    T* ptr;
    MyIter(T* p = nullptr):ptr(p) { }
    T& operator*() const { return *ptr;}
    //...
};

template<typename I>
typename I::value_type  //函数func()的返回类型,为I类型迭代器中的value_type
func(I ite)
{
    return *ite;
}
int main()
{
    MyIter<int> ite(new int(8));
    cout<<func(ite);    //输出8
    return 0;
}

func()函数的返回值必须加上关键字typename,用来告诉编译器这时一个模板类型。但并不是所有迭代器都为class type,原生指针就不是,它就不能定义内嵌型别。这时模板偏特化(template partial specialization)就能解决这个问题。

偏特化的意义

如果class template拥有一个以上的template参数,我们可以针对其中某个(或数个,但并非全部)template参数进行特化工作。也就是将泛化版本中的某些template参数给予明确的指定。

如:

template<typename U, typename V, typename T>
class C { }

偏特化不是template参数U、V或T指定某个参数值,而是针对(任何)template参数更进一步的条件限制所设计出来的一个特化版本。看这个例子:

//泛化版本
template<typename T>
class C { }
//偏特化版本
template<typename T>
class C<T*> { } //解决原生指针的问题

如此便能解决前面的内嵌型别的问题。下面这个class template专门用来萃取迭代器的特性之一 :value_type

template<typename I>
struct Iterator_traits  //traits指的是特性
{
    typedef typename I::value_type value_type;
}

以上是关于STL之traits编程技法的主要内容,如果未能解决你的问题,请参考以下文章

STL源码剖析——iterators与trait编程#2 Traits编程技法

traits编程技法

STL源码分析--traits

模板参数推导

STL源码剖析——Iterators与Traits编程#5 __type_traits

STL源代码分析--萃取编程(traits)技术的实现