c++ 类型萃取

类型萃取

类型萃取是基于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;
}

猜你喜欢

转载自blog.csdn.net/M_jianjianjiao/article/details/85224770