STL 萃取(Traits)机制剖析

模板特化

在将萃取机制之前,先要说明模板特化

当有两个模板类,一个是通用泛型模板,一个是特殊类型模板,如果创建一个特殊类型的对象,会优先调用特殊的类型模板类,例如:

template <typename T>   //泛型模板
class MyClass
{
public:
    MyClass()
    {
        cout << "T MyClass!" << endl;
    }
    ~MyClass()
    {
        cout << "~T MyClass!" << endl;
    }
};

template<>
class MyClass<int>  //全特化模板
{
public:
    MyClass()
    {
        cout << "int MyClass!" << endl;
    }
    ~MyClass()
    {
        cout << "~int MyClass!" << endl;
    }
};

int main()
{
    MyClass<char> mc0;
    MyClass<int> mc1;
    return 0;
}

运行结果:

T MyClass!
int MyClass!
~int MyClass!
~T MyClass!

萃取机制

现在举一系列例子来说明萃取机制

现在有两个类,需要完成相同的功能GetSum返回求和值

//int类型
class IntArray
{
public:
    IntArray()
    {
        a = new int[10];
        for (int i = 0; i < 10; ++i)
        {
            a[i] = i + 1;
        }
    }
    ~IntArray()
    {
        delete[] a;
    }

    int GetSum(int times)   //对整数求和
    {
        int sum = 0;
        for (int i = 0; i < 10; ++i)
            sum += a[i];
        cout << "int sum=" << sum << endl;
        return sum * times;
    }
private:
    int *a;
};

//Float类型
class FloatArray
{
public:
    FloatArray()
    {
        f = new float[10];
        for (int i = 1; i <= 10; ++i)
        {
            f[i - 1] = 1.0f / i;
        }
    }
    ~FloatArray()
    {
        delete[] f;
    }
    float GetSum(float times)   //对浮点数求和
    {
        float sum = 0.0f;
        for (int i = 0; i < 10; i++)
            sum += f[i];
        cout << "float sum=" << sum << endl;
        return sum * times;
    }
private:
    float* f;
};

我们可以看到,这样写代码冗余度很高,一部分功能比如GetSum函数,两个类都有,能不能用一个类完成?

先定义一个类,通过泛型,调用对应对象的GetSum函数得到结果。

template<class T>
class Apply
{
public:
    float GetSum(T& t, float inarg)
    {
        return t.GetSum(inarg);
    }
};

这种方法不能完全解决我们的问题(函数返回值和参数类型固定,就会导致异常),如何解决变化的输入输出参数?traits技术就能解决问题。

template<class T>   //可以什么都不用写,说明定义了一个模板类
class NumTraits
{};

//模板特化IntArray
template<>
class NumTraits<IntArray>
{
public:
    typedef int resulttype;
    typedef int inputargtype;
};
//模板特化FloatArray
template<>
class NumTraits<FloatArray>
{
public:
    typedef float resulttype;
    typedef float inputargtype;
};

template<class T>
class Apply2
{
public:
    NumTraits<T>::resulttype GetSum(T& obj, NumTraits<T>::inputargtype inputarg)
    {
        return obj.GetSum(inputarg);
    }
};

int main()
{
    IntArray intary;
    FloatArray floatary;
    Apply2<IntArray> ai2;  //采用萃取
    Apply2<FloatArray> af2; //采用萃取
    cout << "2整型数组的和3倍:" <<ai2.GetSum(intary,3) << endl;    //返回整形
    cout << "2浮点数组的和3.2倍:" << af2.GetSum(floatary,3.2f) << endl;    //返回浮点型
    return 0;
}

为什么两个类中都定义了resulttype和inputargtype,为什么要把返回类型、输入参数,都定义为相同的名称呢?因为为了编制模板类共同的调用接口做准备。

为了简化Apply2函数的定义形式,再次巧妙运用typedef进行定义,代码如下,与原始功能相同。

//泛型模板类
template<class T>
class NumTraits
{}; //可以什么都不用写,说明定义了一个模板类

template<> //模板特化
class NumTraits<IntArray>
{
public:
    typedef int resulttype;
    typedef int inputargtype;
};

template<> //模板特化
class NumTraits<FloatArray>
{
public:
    typedef float resulttype;
    typedef float inputargtype;
};

template<class T>
class Apply2
{
public:
    typedef NumTraits<T>::resulttype result;
    typedef NumTraits<T>::inputpara input;

    result GetSum(T& obj, intput inputarg)
    {
        return obj.GetSum(inputarg);
    }
};

总结

萃取机制在STL中被广泛运用,借助模板特化和和typedef可以将接口做到通用,降低了代码的冗余度,提高了代码的复用

?

原文地址:https://www.cnblogs.com/WindSun/p/11450701.html

时间: 2024-09-30 10:25:16

STL 萃取(Traits)机制剖析的相关文章

[C++]STL萃取学习

STL萃取学习 一,萃取模板类实现 iterator类:模板常用属性的集合类,其他类只需要集成该类即可.本例为学习就只包括value_type属性. iterator_traits类:属性萃取类. /********************************* * * Author : szyu * * Date : 2017.3.1 * **************************************/ #ifndef __SZYU_ITERATOR__ #define __

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

1.为什么要出现? 按照默认认定,一个模板给出了一个单一的定义,可以用于用户可以想到的任何模板参数!但是对于写模板的人而言,这种方式并不灵活,特别是遇到模板参数为指针时,若想实现与类型的参量不一样的实例化,就变得不太可能了!也有时,想禁止此种相同的实例化变得不太可能!故而出现了,Partial Specialization! 同时,在使用void*指针时,可以最大限度的共享代码,减少代码的膨胀! 2.它是什么?其实,就是用户定义的偏特化.用template<>来说明这是一个偏特化,针对任何模板

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

1.为什么要出现? 依照默认认定.一个模板给出了一个单一的定义,能够用于用户能够想到的不论什么模板參数!可是对于写模板的人而言,这样的方式并不灵活.特别是遇到模板參数为指针时,若想实现与类型的參量不一样的实例化.就变得不太可能了!也有时.想禁止此种同样的实例化变得不太可能! 故而出现了,Partial Specialization! 同一时候,在使用void*指针时.能够最大限度的共享代码,降低代码的膨胀! 2.它是什么?事实上,就是用户定义的偏特化.用template<>来说明这是一个偏特化

STL的迭代器和类型萃取

今天就可以把STL库中迭代器的实现,和类型萃取好好整理一下了 迭代器的设计思维是STL的关键所在,在STL的实际运用和泛型思维,迭代器都扮演着十分重要的角色,STL力求把数据容器和算法的概念分开来,于是就有了STL的两大部分,容器(container)和泛型算法(algorithms),泛型算法有很多参数都是迭代器. 举一个栗子!泛型算法find()的实现! 1 template<class InputIterator, class T> 2 InputIterator find(InputI

STL学习_萃取技术__type_traits

之前在学习STL库中的析构工具destory()时,提到过这样一句话,此函数设法找到元素的数值型别,进而利用__type_traits<>求取适当措施.一直难以理解,现在自己总结了下自己对萃取技术的理解. 让自己困惑的程序: template<class T> void destroy(T *pointer) { pointer->~T(); } template<calss ForwardIterator> void destroy(ForwardIterato

STL(七)之萃取技术

traits技术 原理:利用template的参数推导机制获取传入的参数型别. template<typename T> struct Iter { typedef T value_type; .... } template<typename T> typename T::value_type func(T* ite) {return *ite;} 这种程度,依旧会遇到一个问题:如果不是一个class type(比如指针,引用),就无法进行正确的参数推导.可以使用模板偏特化来处理这

C++之萃取技术(traits)

为什么需要类型萃取 前面我们提到了迭代器,它是一个行为类似于smart pointer之类的东西,主要用于对STL容器中的对象进行访问,而且不暴露容器中的内部结构,而迭代器所指对象的型别称为该迭代器的value type;如果在实际的工程当中我们应该怎么获取STL容器中对象的value type 呢,这里面就需要用到C++中模板的特化了,我们先来看看下面的代码: template <class T> void Func() { cout << "非内置类型" &

STL中的Traits编程技法

最近在看读<STL源码剖析>,看到Traits编程技法这节时,不禁感慨STL源码作者的创新能力.那么什么是Traits编程技法呢?且听我娓娓道来: 我们知道容器的许多操作都是通过迭代器展开的.其中容器类似于数组,迭代器类似于指针.我们用数组来写个例子: 1 int arr[5] = {1,2,3,4,5}; 2 int *p; 3 p = &arr[2]; 假设,我将第1.2遮挡起来,问你p所指向的对象arr[2]是什么类型,你恐怕无法回答.因为它可以是int,char,float甚至

STL iterator和traits编程技法

今天终于看完了<STL源码分析>,最近忙于两个比赛的各种文档,没时间写东西,趁着看完的劲,把欠下的补上来. <Design patterns>中对于iterator模式描述如下:提供一种方法,使之能够依序寻访某个聚合物所含的各个元素,而又无需暴露该聚合物的内部结构.在STL中,iterator扮演着连接container和algorithms的作用,下面以STL find()函数展现一下iterator在container和algorithm之间的连接作用. template &l