C++模板的类型萃取

个人博客传送门
类型萃取,是C++中的一种编程技术。当我们希望对模板传递的不同类型进行不同的操作的时候,同时我们又不希望改变该模板的封装方式。我们可以通过这种技术,对传入的不同类型进行不同的原理操作。

特化

要明白类型萃取,首先要知道模板中的特化。一般来说,我们的模板是通用类型的,但是如果有一些类型,我们希望有不同的操作方式,我们就可以通过特化的方式。例子如下:

#include <iostream>

using namespace std;

//模板的一般版本
template <class T>
class number{
public:
    void show(){
        cout << "number" << endl;
    }
};
//模板的int类型特化版本
template <>
class number<int>{
public:
    void show(){
        cout << "int" << endl;
    }
};

int main(){
    system("clear");
    number<int> numint;
    numint.show();

    number<float> numfloat;
    numfloat.show();

    number<char> numchar;
    numchar.show();
    return 0;
}

只有int类型才会输出int,其它的就像是float和char类型输出的都是number
特化的输出
特化的方式,其实是十分冗余的。如果我的number类有很多的封装,那么实现它的特化,就需要将这些封装重新实现一遍。这样的复用性就十分低。

类型萃取TypeTraits

关于类型萃取的知识,可以看看我的这篇读书笔记中的3.3和3.4
我的个人博客文章地址
我的CSDN博客文章地址
这里我进行一个对于自创类SeqList类(对STL中vector的模拟)的类型萃取举例,情景说明:这里我想要对模板类SeqList进行拷贝,涉及到一个问题。如果我的元素类型是string的话,我必须进行深拷贝,否则就会出现奔溃的情况,这是对内存的使用出现问题。当我的元素类型是int、float、char等平凡类型(即POD:plain old data,基本类型,这些类型的拷贝不会涉及到内存的使用异常),我就可以使用浅拷贝,这样比起深拷贝提高了效率。
这个时候,我通过在SeqList类中进行类型萃取,就可以实现两种不同的拷贝方式:

//定义两个空类
struct __TrueType{};
struct __FalseType{};

//一般类型及特化(内嵌重定义IsPODType)
template<class T>
struct __TypeTraits{ typedef __FalseType IsPODType; };

template<>
struct __TypeTraits<int>{ typedef __TrueType IsPODType; };

//实现功能函数(用__TrueType/__FalseType实现重载)
template <class T>
T* __TypeCopy(T* dst, const T* src, size_t n, __TrueType){
    //浅拷贝,调用memcpy
    return (T*)memcpy(dst, src, n*sizeof(T));
}
template <class T>
T* __TypeCopy(T* dst, const T* src, size_t n, __FalseType){
    //深拷贝,进行了 operator= 调用
    for(size_t i = 0; i<n; ++i){
        dst[i] = src[i];
    }
    return dst;
}
//对外接口(实现IsPODType的__TrueType和__FalseType的转换)
template <class T>
T* TypeCopy(T* dst, const T* src, size_t n){
    return __TypeCopy(dst, src, n, __TypeTraits<T>::IsPODType);
}
//调用
int main(){
    int a1[3] = {1, 2, 3};
    int a2[2] = {0, 0, 0};

    string s1[3] = {"1", "2", "3"};
    string s2[3] = {"0", "0", "0"};

    TypeCopy(a1, a2, 3);
    TypeCopy(s1, s2, 3);

    return 0;
}

这样,当传入的参数是s1,s2的时候,__TypeTraits调用的是一般版本,IsPODType__FalseType,这样__TypeCopy调用的是__FalseType的重载版本,进行深拷贝。当传入的参数是a1,a2的时候,调用的是__TrueType的重载版本,进行浅拷贝。这里只对int进行了特化,所以只有int可以调用__TrueType的版本。但是我们可以对float、double等PODType进行特化,这样就大大提高了代码的复用性。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值