• 提出问题:如何实现一个对于拷贝内置类型和自定义类型通用的拷贝函数?

1、拷贝内置类型

对于内置类型我们可以用memcpy进行拷贝,因为memcpy属于浅拷贝,内置类型不涉及资源管理的问题。

2、拷贝自定义类型

拷贝自定义类型时有可能会涉及到深拷贝(如string)涉及到了资源管理,就不能使用memcpy。

所以给出了一种方法:赋值

void Copy(T* dst, const T* src, size_t size)
{for (size_t i = 0; i < size; ++i) { dst[i] = src[i]; }
}int main()
{std::string strarr1[3] = { "11", "22", "33" };   std::string strarr2[3];   Copy(strarr2, strarr1, 3);return 0;
}

我们使用循环赋值的方式来进行拷贝,但发现这样做效率很低。


  • 那能否将上述两种方法结合起来,遇到内置类型就用memcpy来拷贝,遇到自定义类型就用赋值方式来做呢?

改进一  我们增加一个bool类型区分 内置类型 与 自定义类型 。

true就是内置类型,false就是自定义类型。

void Copy(T* dst, const T* src, size_t size, bool IsPODType)
{if(IsPODType)memcpy(dst, src, sizeof(T)*size);else{for (size_t i = 0; i < size; ++i){dst[i] = src[i];}}
}

但发现这样做,用户就需要手动的添加最后一个参数,易出错。

那能否让一个函数自动去识别所拷贝类型是内置类型或者自定义类型呢?

改进二  使用函数区分内置于自定义类型

bool IsPODType(const char* strType)
{// 此处只是举例,只列出个别类型 const char *arrType[] = { "char", "short", "int", "long", "long long", "float", "double", "long double" };        for (auto e : arrType){if (strcmp(e, strType) == 0)return true;}return false;
}template<class T>
void Copy(T* dst, const T* src, size_t size)
{if(IsPODType(typeid(T).name())            //typeid来确认所拷贝对象的实际类型memcpy(dst, src, sizeof(T)*size);else{for (size_t i = 0; i < size; ++i){dst[i] = src[i];}}
}

但这样做需要将所有的类型遍历一遍,且每次比较都是字符串的比较,效率较低。

改进三  类型萃取

为了将内置类型与自定义类型区分开,给出以下两个类分别代表内置类型与自定义类型。

//代表内置类型
struct TrueType {static bool Get(){return true;}
};
//代表自定义类型
struct FalseType {static bool Get(){return false;}
};

再给出类模板,用户可以按照任意类型实例化该模板

通过将基本类型每个都特化一次,在识别时就可以直接确定出所传入的参数的类型。

在对基本类型特化时,必需要将所有的类型都特化一变,包括有符号和无符号的类型。这里只给出了几种。

//给出模板
template<class T>
struct TypeTraits
{ typedef FalseType IsPODType;
};//对上述的类模板进行以下方式的实例化
template<>
struct TypeTraits<char>
{ typedef TrueType IsPODType;
};
template<>
struct TypeTraits<short>
{ typedef TrueType IsPODType;
};
template<>
struct TypeTraits<int>
{ typedef TrueType IsPODType;
};
template<>
struct TypeTraits<long>
{ typedef TrueType IsPODType;
};

类型萃取总代码:

#include <iostream>
#include <string>//代表内置类型
struct TrueType {static bool Get(){return true;}
};
//代表自定义类型
struct FalseType {static bool Get(){return false;}
};//给出模板
template<class T>
struct TypeTraits
{ typedef FalseType IsPODType;
};
//对上述的类模板进行以下方式的实例化
template<>
struct TypeTraits<char>
{ typedef TrueType IsPODType;
};
template<>
struct TypeTraits<short>
{ typedef TrueType IsPODType;
};
template<>
struct TypeTraits<int>
{ typedef TrueType IsPODType;
};
template<>
struct TypeTraits<long>
{ typedef TrueType IsPODType;
};template<class T>
void Copy(T* dst, const T* src, size_t size)
{//通过对TypeTraits类模板,来确认所拷贝对象的实际类型if(TypeTraits<T>::IsPODType::Get())memcpy(dst, src, sizeof(T)*size);else{for (size_t i = 0; i < size; ++i){dst[i] = src[i];}}
}int main()
{int a1[] = { 1,2,3,4,5,6,7,8,9,0 };   int a2[10];   Copy(a2, a1, 10);  //内置类型调用特化 intstd::string strarr1[3] = { "11", "22", "33" };   std::string strarr2[3];   Copy(strarr2, strarr1, 3); //自定义类型调用模板return 0;
}

C++特化的应用——类型萃取相关推荐

  1. C++ — 类型萃取

    类型萃取 在编程中我们可能时常会听到类型萃取这个高大上的"学术名词",我们今天来探究一下这个高大上的学术名词 到底是何方神圣,先看看官方的解释类型萃取使用模板技术来萃取类型(包含自 ...

  2. C/Cpp / STL / 类型萃取

    作用 类型萃取使用模板技术来萃取类型(包含自定义类型和内置类型)的某些特性,用以判断该类型是否含有某些特性,从而在泛型算法中来对该类型进行特殊的处理用来达到提高效率或者其他的目的. 类型萃取的实现的基 ...

  3. C++的类型萃取技术

    http://www.cppblog.com/nacci/archive/2005/11/03/911.aspx?spm=0.0.0.0.iyJqvt&file=911.aspx 自从C++中 ...

  4. C++之类型萃取技巧

    使用类型萃取的原因 就是当你的顺序表是自定义类型,我们进行顺序表增容的时候,这个时候会出现一个问题,比如string类型,这个类型中有一个_buf与_ptr,当储存少于16个的时候这时会储存在_buf ...

  5. C++ 模板类型萃取技术 traits

    当函数,类或者一些封装的通用算法中的某些部分会因为数据类型不同而导致处理或逻辑不同(而我们又不希望因为数据类型的差异而修改算法本身的封装时),traits会是一种很好的解决方案.(类型测试发生在编译期 ...

  6. [c++]——什么是类型萃取

    类型萃取 类型萃取从字面意思上来说其实就是帮助我们挑选某个对象的类型,筛选特定的对象来做特定的事. C++中的类型萃取并不是每个人都熟知,他们一般都出现在STL库底层的实现原理中,和笔者一样,相信听到 ...

  7. C++类型萃取之type_traits和type_info

    类型萃取 类型判断 typeid decltype和declval enable_if 类型萃取 通过type_traits可以实现在编译期计算.查询.判断.转换和选择,增强了泛型编程的能力,也增强了 ...

  8. type_traits 类型萃取

    一. c++ traits traits是c++模板编程中使用的一种技术,主要功能: 把功能相同而参数不同的函数抽象出来,通过traits将不同的参数的相同属性提取出来,在函数中利用这些用traits ...

  9. C++模板编程之类型萃取 惊鸿一瞥

    一.从模板函数std::distance(计算迭代器的距离)开始 #include <iostream> #include <vector> #include <list ...

最新文章

  1. 30分钟掌握ES6/ES2015核心内容
  2. 《中国人工智能学会通讯》——12.38 知识库与 HTML 表格的融合
  3. 知识产权创业的比赛结果
  4. Visual C++——CComboBox控件在对话框中没有下拉项目问题解决方案
  5. 什么行业需要java_java开发可以从事什么行业
  6. 女程序员被阿里录取工资二万六,辞职时被领导挽留:给你四万留下
  7. 如何处理错误消息Unable to install breakpoint due to missing line number attributes
  8. maven(7)生命周期和插件
  9. CompletableFuture详解~join与get的区别
  10. linux管理员清理主目录,在Linux上如何清理垃圾系统管理员
  11. 使用 PowerShell 自动登录 Azure
  12. 最近在做支付宝支付,在本地测试一切正常,上传到服务器就遇到报错:
  13. mysql id用什么类型_mysql 证明为什么用limit时,offset很大会影响性能
  14. 服务器4通道性能相当于多少人民币,有钱人的世界我们不懂,组装电脑花费百来万,跑分世界第四...
  15. jquery on()方法绑定多个选择器,多个事件
  16. STM8L 库下载地址
  17. 关于ArcGIS新建Person Geodatabase(.mdb)报错的问题
  18. 原子操作、锁、同步实现原理
  19. 识海日志——时间都去哪了(20140311)
  20. 还在为关闭不了win10杀毒软件windows defender而崩溃吗?小编三招教你如何彻底关闭

热门文章

  1. spring api 中文_Spring高级技术梳理
  2. php.inf文件在哪里,php和phpinfphpinfoo
  3. docker 容器安装conposer_Docker下用composer国内镜像安装Laravel
  4. freemarker ftl模板_Spring Boot2 系列教程(十)Spring Boot 整合 Freemarker
  5. matlab正弦序列频谱,【求助】正弦信号序列fft频谱分析!!!
  6. webview 个人小程序_微信小程序新增Webview它是什么东西?
  7. MySQL数据库的总结_MySQL数据库应用总结(三)—MySQL数据库的基本操作
  8. sprintf函数的格式化字符串_尚学堂百战程序员:Python 字符串处理
  9. 复制不用说yes的方法
  10. java加密方式有哪些_面完平安JAVA,他们说了这些