前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >STL 萃取(Traits)机制剖析

STL 萃取(Traits)机制剖析

原创
作者头像
WindSun
修改2019-09-03 09:58:08
1.6K0
修改2019-09-03 09:58:08
举报
文章被收录于专栏:编程技术专栏编程技术专栏

模板特化

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

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

代码语言:txt
复制
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;
}

运行结果:

代码语言:txt
复制
T MyClass!
int MyClass!
~int MyClass!
~T MyClass!

萃取机制

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

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

代码语言:txt
复制
//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函数得到结果。

代码语言:txt
复制
template<class T>
class Apply
{
public:
    float GetSum(T& t, float inarg)
    {
        return t.GetSum(inarg);
    }
};

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

代码语言:txt
复制
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进行定义,代码如下,与原始功能相同。

代码语言:txt
复制
//泛型模板类
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可以将接口做到通用,降低了代码的冗余度,提高了代码的复用

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 模板特化
  • 萃取机制
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档