类型萃取
类型萃取是基于c++中的模板特化来实现的,是对于模板特化的应用。linux
以通用的拷贝函数为例ios
拷贝函数,c++自带的拷贝函数是俗称的浅拷贝,浅拷贝对于一些内置类型而言不会出错,但对于一些自定义类型在拷贝的时候就会出现内存访问错误(中断),想回顾浅拷贝的“同志”能够看https://blog.51cto.com/14233078/24425271.此方案虽然解决了拷贝问题,可是缺点也很明显,在每一次拷贝数据,都须要遍历一遍,时间复杂度O(1)c++
#include<iostream> using namespace std; #include<string> template<class T> void Copy1(T* dst, T* src, size_t size) { memcpy(dst, src, sizeof(T)*size); } // 优势:必定不会出错 // 缺陷:O(N) template<class T> void Copy2(T* dst, T* src, size_t size) { for (size_t i = 0; i < size; ++i) dst[i] = src[i]; } bool IsPODType(const char* strType) { // 此处能够将全部的内置类型枚举出来 const char* strTypes[] = { "char", "short", "int", "long", "long long", "float", "double" }; for (auto e : strTypes) { if (strcmp(strType, e) == 0) return true; } return false; } template<class T> void Copy(T* dst, T* src, size_t size) { // 经过typeid能够将T的实际类型按照字符串的方式返回 if (IsPODType(typeid(T).name())) { // T的类型:内置类型 memcpy(dst, src, sizeof(T)*size); } else { // T的类型:自定义类型---缘由:自定义类型中可能会存在浅拷贝 for (size_t i = 0; i < size; ++i) dst[i] = src[i]; } } void TestCopy() { int array1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; int array2[10]; Copy(array2, array1, 10); string s1[3] = { "1111", "2222", "3333" }; string s2[3]; Copy(s2, s1, 3); } int main() { TestCopy(); return 0; }
C语言参与编译的是.c文件,一个.c文件是一个编译单元。
头文件在预处理阶段被展开,即,预处理器看见#include预处理指令的时候,就用相应头文件的内容替换掉这个#include预处理指令(把头文件内容拷贝到.c文件中,而后删除这条#include预处理指令)。
你应该把头文件看出是导出给外部模块使用的接口,里面存放外部模块须要使用的宏定义及函数原型。
在linux下,能够用gcc -E查看预处理以后的文件。
头文件中的函数原型是提供给编译器做为函数原型检查的,对于不是本源文件中的函数,编译过程当中并不会产生实际的调用代码(函数调用须要知道确切的函数地址),只是在相应的地方作个标记,表示在这里须要调用某个函数。编译完成产生的是汇编代码。
如上所述,编译产生的汇编代码并不能直接运行,由于外部函数调用的地方还没给予确切的函数地址。这个工做由连接过程完成。连接器会查找其它源文件所产生的汇编代码,进而找到正确的函数调用地址,而后用这个地址替换掉在编译时作的标记。完成这一步后,程序就能够实际运行了。
所以,.h是根本不会被编译的,它若是被包含,则会被预处理器将其内容一分不差的拷贝到.c文件中,.编译器编译的是拷贝后的这个.c文件。ide
2.分文件管理:
由于头文件在预处理阶段就已完成,因此不会下降代码效率,所以解决1中代码效率低的问题函数
头文件测试
#pragma once #include<iostream> using namespace std; #include<string> //来自自定义类型 struct TrueType {}; // 对应自定义类型 struct FalseType {}; //隐示实例化 template<class T> struct TypeTraits { typedef FalseType PODTYPE; // plain old data }; //显示实例化 template<> struct TypeTraits<char> { typedef TrueType PODTYPE; }; template<> struct TypeTraits<short> { typedef TrueType PODTYPE; }; template<> struct TypeTraits<int> { typedef TrueType PODTYPE; }; template<> struct TypeTraits<long> { typedef TrueType PODTYPE; }; template<> struct TypeTraits<long long> { typedef TrueType PODTYPE; }; template<> struct TypeTraits<float> { typedef TrueType PODTYPE; }; template<> struct TypeTraits<double> { typedef TrueType PODTYPE; }; void TestCopy();
源代码spa
#include"Type_extraction.h" template<class T> void Copy(T* dst, T* src, size_t size, TrueType) { // T的类型:内置类型 memcpy(dst, src, sizeof(T)*size); } template<class T> void Copy(T* dst, T* src, size_t size, FalseType) { // T的类型:自定义类型---缘由:自定义类型中可能会存在浅拷贝 for (size_t i = 0; i < size; ++i) dst[i] = src[i]; } template<class T> void Copy(T* dst, T* src, size_t size) { Copy(dst, src, size, TypeTraits<T>::PODTYPE()); } void TestCopy() { int array1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; int array2[10]; Copy(array2, array1, 10); string s1[3] = { "1111", "2222", "3333" }; string s2[3]; Copy(s2, s1, 3); }
测试文件main.c.net
#include"Type_extraction.h" int main() { TestCopy(); return 0; }
模板的声明和定义必须放在一个文件缘由
https://blog.csdn.net/chigusakawada/article/details/78752668
显示实例化,隐式实例化概念
https://blog.csdn.net/qiujianjian/article/details/84792608code