C++类型萃取
程序员文章站
2022-06-10 13:48:47
...
在利用模板来实现容器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函数对自定义类型的拷贝是不是也是预料中的结果呢?
调试发现,对自定义类型的拷贝也很成功。
对类型萃取的讲解就到这里,欢迎读者提出宝贵意见哦~
上一篇: layout布局