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