C++ 模板进阶使用

typename使用场景

使用模板中的内嵌类型(如重定义的类型),但模板还没有初始化时,需要加上typename

template <class T>
void print(list<T>& x)
{
	list<T>::iterator it = x.begin();
}

函数接收一个list对象,但list存储的数据类型还未确定,用模板参数代替,接着使用list中重定义的迭代器类型,定义一个迭代器,上面的代码是错的,有两种解释:1.类的静态变量也是这样使用,类名::静态变量名,编译器无法区分。2.类模板没有实例化,没有这个类模板,里面的内嵌类型自然也没有,编译器找不到这个类型,所以报错

正确的写法

template <class T>
void print(list<T>& x)
{
	typename list<T>::iterator it = x.begin();
}

同时,在类外定义函数,并且以内嵌类型作为函数返回值时,也需要加上typename

非类型模板参数

模板参数通常是类型,如int,double,这样的模板参数被称为类型模板参数,除此之外还有非类型模板参数,这个参数只能接收整形值,不能接收浮点数,string这样的对象。

有一个使用非类型模板参数例子,STL库中的array,C++11的更新中加入了array容器,但这个容器实在是太过鸡肋导致很少被使用。array就是一个静态数组,创建array对象时需要两个模板参数,一个是存储的对象类型,为类型模板参数,一个是数组的大小,为非类型模板参数。
在这里插入图片描述
array只是讲解非类型模板参数的一个例子,与原生数组相比,array的唯一优势就是越界的检查严格,而原生数组的检查为抽查,可能检查不出越界。但与vector相比array几乎被吊打。

(非类型模板参数是一个常数,不能修改)
在这里插入图片描述
调用func函数试图修改N的值。
在这里插入图片描述

模板的特化

函数模板的特化

在这里插入图片描述
结果可能是0也可能是1,因为比较的是指针不是指针指向的数据(在堆上开辟空间是随机的),要对指针指向的数据进行比较需要对函数进行特化,

template <class T>
bool Less(T x1, T x2)
{
	return x1 < x2;
}

template<>
bool Less<int*>(int* x1, int* x2)
{
	return *x1 < *x2;
}

特化模板的规则:

1.必须先有一个基础模板
2.关键词template后跟上<>
3.写函数,函数名后跟<>,里面写要特化的类型(比如刚刚的代码,我要特化int*,尖括号里就写int*)
4.函数形参表的数据类型要和模板的类型对应

关于第4点要特别注意,如果函数模板的形参列表的形参为引用,特化函数的形参也要为引用在这里插入图片描述
而特化函数模板其实不如直接写一个函数来的方便,如果实参已经和函数的形参对应,程序会直接调用该函数不会根据模板生成函数在这里插入图片描述
就刚刚的代码,实参为两个int类型的参数,而已经有了形参为两个int类型的函数,所以直接调用这个函数,相比特化函数,还是直接写对应的函数更好,实际中很少使用函数模板的特化

类模板的特化

全特化

类模板的特化和函数特化规则相同,现在有一个基础类test

template<class T1, class T2>
class test
{
public:
	test()
	{
		cout << "class test<T1, T2>" << endl;
	}
};

对test类进行全特化

template<>
class test<int, double>
{
public:
	test()
	{
		cout << "class test<int, double>" << endl;
	}
};

当用int和double实例化类模板时,程序就会走特化模板。

半特化/偏特化

半特化也称偏特化,半特化是对模板参数进一步的限制,体现在两个方面:1.对部分参数的特化。2.对参数的限制。

对于上面的基础类模板,可以将第二个参数特化为char

template<class T>
class test<T, char>
{
public:
	test()
	{
		cout << "class test<T, char>" << endl;
	}
};

也能将参数限制成指针或者引用

template<class T1, class T2>
class test<T1*, T2*>
{
public:
	test()
	{
		cout << "class test<T1*, T2*>" << endl;
	}
};

这样的话,如果用两个指针实例化模板就会调用这个特化版本。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值