您好,登录后才能下订单哦!
类型萃取
类型萃取是基于c++中的模板特化来实现的,是对于模板特化的应用。
以通用的拷贝函数为例
拷贝函数,c++自带的拷贝函数是俗称的浅拷贝,浅拷贝对于一些内置类型而言不会出错,但对于一些自定义类型在拷贝的时候就会出现内存访问错误(中断),想回顾浅拷贝的“同志”可以看https://blog.51cto.com/14233078/2442527
1.此方案虽然解决了拷贝问题,但是缺点也很明显,在每一次拷贝数据,都需要遍历一遍,时间复杂度O(1)
#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文件。
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();
源代码
#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
#include"Type_extraction.h"
int main()
{
TestCopy();
return 0;
}
模板的声明和定义必须放在一个文件原因
https://blog.csdn.net/chigusakawada/article/details/78752668
显示实例化,隐式实例化概念
https://blog.csdn.net/qiujianjian/article/details/84792608
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。