C++类型萃取

来源:互联网 发布:pre绘图软件 编辑:程序博客网 时间:2024/05/29 14:42
  在利用模板来实现容器vector的时候,由于是泛型编程,所以参数类型是可以说是任意的,而当我们希望实现对一块连续空间进行拷贝的时候,有两种实现方式,一种是memcpy函数实现,另一种则是通过for循环一个一个赋值。   memcpy是一种很高效的方式,但是,当拷贝自定义类型时就会牵扯到深浅拷贝的问题,因为memcpy的实现方式是浅拷贝,在释放内存的时候往往会因为多次释放同一块内存而导致程序崩溃。   所以当拷贝自定义类型时就需要采用for循环一个一个赋值(赋值运算符重载的时候的实现方式是深拷贝)的方式来实现拷贝了。可能有人会有疑问,为什么不直接选择将所有的拷贝方式都用for循环来实现呢。因为for循环的效率很低。而memcpy的效率高,而且当T为内置类型时,memcpy不仅不会出错而且效率还很高。   自然而然地,就想到利用一个方法能够实现在拷贝内置类型的时候使用memcpy,拷贝自定义类型的时候使用for循环。这样就既保证了程序既不会出错又高效。接下来就来实现这种方法-------**类型萃取**。

看代码:

struct TrueType{    bool Get()    {        return true;    }};struct FalseType{    bool Get()    {        return false;    }};

首先定义了TrueType和FalseType两个类,注意这两个类都是用struct关键字声明的,这是为了让类里边的成员默认为公有的,用class关键字来声明也可以,只要在类成员里边加将其声明为公有的就行了。

template<typename Ty>struct TypeTraits{    typedef FalseType IsPODType;};

这段代码声明了一个类模板,在类模板里边就只做一件事情,将FalseType重命名为 IsPODType 。在这个模板类中将所有的类型假定都为自定义类型。说明: IsPODType 是在类TypeTraits里边声明的,也就相当于类 TypeTraits 的一个成员类型,之后使用它的时候需要加 TypeTraits::作用域,记住,IsPODType 不是一个成员变量,只是一个成员类型,在后边的第一个测试函数会加以验证。
接下来要做的事情就是对内置类型进行特化。

template<>struct TypeTraits<int>{    typedef TrueType IsPODType;};template<>struct TypeTraits<char>{    typedef TrueType IsPODType;};template<>struct TypeTraits<short>{    typedef TrueType IsPODType;};template<>struct TypeTraits<size_t>{    typedef TrueType IsPODType;};template<>struct TypeTraits<long>{    typedef TrueType IsPODType;};template<>struct TypeTraits<double>{    typedef TrueType IsPODType;};template<class Ty>struct TypeTraits<Ty*>{    typedef TrueType IsPODType;};

在这里给出部内置类型的特化,相信读者已经看懂如何去特化参数为内置类型的类了,就不一一实现了。

接下来就是拷贝函数了

template<typename T>void Copy(T* dest, const T* src, size_t size){    //获取参数的类型的名称    cout << "Typename is: " << typeid(T).name() << endl;    if (TypeTraits<T>::IsPODType().Get())//是内置类型    {        memcpy(dest, src, size*sizeof(T));    }    else    {        for (size_t i = 0; i < size; i++)        {            dest[i] = src[i];        }    }}

**注意:**typeid可以获取到一个类型的名称,但是不能拿来做变量的声明。

最后就是测试函数了

void FunTest1()//测试内置类型{    cout << sizeof(TypeTraits<int>) << endl;    int arr[] = { 1, 2, 3, 4, 5, 6 };    int array[10] = { 0 };    size_t size = sizeof(arr) / sizeof(arr[0]);    Copy(array, arr, size);    for (size_t i = 0; i < size; i++)    {        cout << array[i] << " ";    }    cout << endl;}void FunTest2()//测试自定义类型{    string s1[10] = { "1235", "2abdc", "hdfiig", "asdfghjk" };    string s2[10] = { "11", "22", "33" };    Copy(s2, s1, 10);}int main(){    FunTest1();    FunTest2();    return 0;}

先将第二个测试函数的调用注释掉,看第一个测试函数的结果:
这里写图片描述

对类TypeTraits求大小发现其大小为1,这说明这个类里边什么都没有,即IsPODType是并不是其成员变量。
Copy函数对内置类型进行拷贝,意料中的结果。调试看看Copy函数对自定义类型的拷贝是不是也是预料中的结果呢?
这里写图片描述

调试发现,对自定义类型的拷贝也很成功。

对类型萃取的讲解就到这里,欢迎读者提出宝贵意见哦~

原创粉丝点击