类型萃取
类型萃取是基于c++中的模板特化来实现的,是对于模板特化的应用。
关于c++的模板特化
当我们写一个同用的拷贝函数时,我们可以使用mymcpy进行拷贝,但是mymcpy是一个浅拷贝,对于一些基本类型的拷贝效率很高。但是对于要深拷贝的类型来说就不适用了,对于深拷贝我们可以使用for循环的方式来进行。
所以将两者进行结合,当基本类型进行拷贝时使用mymcpy,当自定义类型进行拷贝时使用for循环的方式。
使用函数的方式进行实现
#include <iostream>
#include <cstring>
#include <typeinfo>
#include <string>
using namespace std;
/*
*使用函数进行通用拷贝的实现,但时在基本类型的确定时需要循环,仍然造成一些效率问题
*
*
*/
template<class T>
bool IsBasicType(const T* Type){
const char* type_arr[] = { "int" , "char" , "float" , "double" , "long" , "short" , "long long" }; //这里仅列举了部分的基本类型
for(int i = 0 ; i < sizeof(type_arr)/sizeof(type_arr[0]); ++i)
{
if(strcmp(type_arr[i] , Type) == 0)
return true;
return false;
}
}
template<class T>
void Copy(T* dest , T* src, size_t size){
if(IsBasicType(typeid(T).name()))
memcpy(dest,src,size*sizeof(T));
else{
for(int i = 0; i < size; i++)
{
dest[i] = src[i];
}
}
}
int main()
{
// string s1[] = {"www" , "eee" , "rrr"};
// string s2[3];
float s1[] = {11.1,33.2,33.4};
float s2[3];
Copy<float>(s2,s1,3);
for(int i = 0; i < sizeof(s2)/sizeof(s2[0]); ++i)
cout << s2[i] << endl;
return 0;
}
以上的函数虽然可以区分基本类型和自定义类型,但是在判断是否为自定义类型时需要,循环并且需要strcmp进行字符串比较,所以效率较大。
如果我们要想让函数能够自动识别是基本类型还是自定义的类型,这时我们就需要用到类型萃取了。
类型萃取实质上就是对于模板特化的应用,通过将基本类型每个都特化一次,在识别时就可以直接确定出所传入的参数的类型。
- 在对基本类型特化时,必需要将所有的类型都特化一变,包括有符号和无符号的类型
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
/*使用类型萃取
*使用模板的特化,将所有的模板进行特化,使其能够自动识别,从而少了之前
* 循环判断类型
*/
//先定义两个类型的类,其中包含一个静态的方法用于返回判断条件所需的真假
//标识基本类型
struct BasicType{
static bool Get(){
return true;
}
};
//标识自定义类型
struct DefineType{
static bool Get(){
return false;
}
};
/*创建一个模板类用于识别是基本类型还是自定义类型
由于基本类型都被特化了,所以调用基础模板函数的就是自定义类型
使用一个IsBsicType 来进行类型的重定义,以便调用Get()
*/
template<class T>
struct Type_recog{
typedef DefineType IsBasicType;
};
//这里只列举了部分的基本类型
template<>
struct Type_recog<int>{
typedef BasicType IsBasicType;
};
template<>
struct Type_recog<char>{
typedef BasicType IsBasicType;
};
template<>
struct Type_recog<short>{
typedef BasicType IsBasicType;
};
template<>
struct Type_recog<float>{
typedef BasicType IsBasicType;
};
template<>
struct Type_recog<double>{
typedef BasicType IsBasicType;
};
template<>
struct Type_recog<long>{
typedef BasicType IsBasicType;
};
template<>
struct Type_recog<long long>{
typedef BasicType IsBasicType;
};
template<class T>
void Copy(T* dest, T* src ,size_t size){
if(Type_recog<T>::IsBasicType::Get())
memcpy(dest,src,size*sizeof(T));
else {
for(int i = 0; i < size; i++)
dest[i] = src[i];
}
}
int main(){
// string s1[] = {"www","eee","rrr"};
// string s2[3];
int s1[] = {1,2,3};
int s2[3];
Copy<int>(s2,s1,3);
for(int i = 0; i < sizeof(s2)/sizeof(s2[0]); ++i)
cout << s2[i] << endl;
return 0;
}