您的位置:首页 > 编程语言 > C语言/C++

小结 | C++模板的类型萃取

2018-02-24 17:25 232 查看
个人博客传送门

类型萃取,是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进行特化,这样就大大提高了代码的复用性。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  模板 c++ 类型萃取