更深层次谈c++模板(非类型模板参数,模板的特化,模板分离编译)

1、非类型模板参数

        之前提及的模板参数全部都是类型,其实模板的参数也可以是非类型的常量。如下面这个模板

template<class T, int N>
class Array
{
	T _a[N];
};

int main()
{
	Array<int, 100> ar1;
	return 0;
}

        这实际上是实现了一个定长度的数组,stl里的array的实现原理就是如此,由传入模板参数的数字确定。

        需要注意几点。(1)非类型的模板参数在传参时,只能传常量,及不能用变量来传参。(2)只有整形家族能做非类型模板参数,即char、int、long、long long等,浮点类型和自定义类型不能做模板参数。

2、模板的特化

        通常情况下,使用模板可以实现一些与类型无关的代码,如实现一个进行变量比较的函数模板,如下。

template<class T>
bool IsEqual(T a, T b)
{
	return a == b;
}

int main()
{
	cout << IsEqual(1, 2) << endl;
	cout << IsEqual(1.1, 1.1) << endl;
	cout << IsEqual("abc", "abc") << endl;
	return 0;
}

        但是在进行字符串比较的时候,传入函数的参数时字符串的首地址,即两个地址进行比较,这显然是不正确的,我们希望的是堆字符串的内容进行比较。这也是这种写法的局限性。这个时候解决方法是模板的特化,特化是对某些类型的特殊化处理。如下。

template<class T>
bool IsEqual(T a, T b)
{
	return a == b;
}

template<>
bool IsEqual<const char*>(const char* a, const char* b)
{
	return strcmp(a, b) == 0;
}

int main()
{
	cout << IsEqual(1, 2) << endl;
	cout << IsEqual(1.1, 1.1) << endl;
	const char* a = "abc";
	const char* b = "bcd";
	cout << IsEqual(a, b) << endl;
	return 0;
}

        类模板也可以特化。

template<class T>
class Data
{
	T _dt;
};

template<>
class Data<char>
{
	char _dt;
};

        以上的特化为全特化的情况,也可以有偏特化的情况,更加灵活。如下。

template<class T1, class T2>
class Data
{
	T1 d1;
	T2 d2;
};

template<class T1>
class Data<T1, int>
{
	T1 d1;
	int d2;
};

template<>
class Data<int, int>
{
	int d1;
	int d2;
};

        上面的为原始模板,第二个是一个偏特化(也称半特化)的模板,第三个是全特化的模板。注意(1)在参数匹配的上的情况下,编译器会优先调用已经特化的函数模板或者类模板。(2)不论是偏特化还是全特化的模板,本质还是模板,并没有实例化。

3、模板分离编译

        在工程中我们一般是函数的声明和定义分离,便于维护代码。但是函数模板我们是不会声明和定义分离的,将函数模板放在头文件中。这是因为,编译器不会编译模板本身的,在预处理阶段,编译器检查我们主程序调用模板的地方进行特定实例化,如果模板的声明和定义分离,在定义的文件中如果没有调用模板,则不会实例化特定的函数或者类,在主程序中会链接不上。

        怎么解决上述问题?

        (1)对模板进行显式实例化

template<class T>
bool IsEqual(T& left, T& right)
{
	return left == right;
}

template
bool IsEqual<int>(int& left, int& right);

        在定义的文件中显式的实例化就可以了

        (2)将模板的定义写在头文件中,简单粗暴。

4、模板总结

优点(1)模板复用了代码,节省资源,更快的迭代开发。(2)增强了代码的灵活性。

缺点(1)会导致代码膨胀问题,也会导致编译时间变长。这是因为编译器根据模板的调用实例化出函数或者类。(2)出现模板编译错误时,编译信息非常凌乱,不易定位错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值