C++ - 非类型模版参数和模版的特化

目录

非类型模版参数

模版的特化

函数模版特化

类模版特化

全特化

半特化(偏特化)

参数更进一步的限制


非类型模版参数

在之前学过的例子来看,我们使用模版,它们的参数都是类型模版,根据类型来决定实例化

扫描二维码关注公众号,回复: 15341340 查看本文章

而模版其实还有一种参数,叫做 非类型模版参数

//非类型模版参数 --- 常量
template<typename T, size_t N>     
class array
{
private:
	T _arr[N];
};

int main()
{
	int a = 10;
	const int i = 10;
	fjz::array<int, a> arr1;   //a是变量,编译会报错
	fjz::array<int, i> arr2;   
	fjz::array<int, 10> arr3;
}

非类型模版参数,它是一个常量,所以如果要传参,也必须只能传一个常量,传变量会报错!!

模版的特化

C++支持了模版之后,给我们写代码带了了很大的便利,而模版的特化,更是近一步优化了模版的特点!

看这样一种场景

template<typename T>
bool less(T v1, T v2)
{
	return v1 < v2;
}

int main()
{
    int i1 = 5;
	int i2 = 4;

	int* p1 = &i1;
	int* p2 = &i2;

	cout << fjz::less<int>(i1, i2) << endl;
	cout << fjz::less<int*>(p1, p2) << endl;
	cout << endl;
}

如果我们不是想比较指针的大小,而是想比较指针解引用的数据的大小,那么遇上这种情况怎么办?  使用函数模版特化或者是类模版特化

函数模版特化

template<typename T>
bool less(T v1, T v2)
{
	return v1 < v2;
}

//函数模版特化格式
template<>
bool less<int*>(int* v1, int* v2)
{
	return *v1 < *v2;
}

这时我们就可以对于int* 这一类型进行专门的特化,一旦是发现T类型是int*,就会使用特化版本!

类模版特化

类模板的特化相对于函数模版的特化,多了几种特化形式,适用于不同的场景,更加灵活!

全特化

类模版的全特化与函数模版特化一样

//原模版
template<typename T1, typename T2>
class A {
public:
	void func(T1 t1, T2 t2)
	{
		std::cout << "class A" << std::endl;
	}
};

//全特化
template<>
class A<int, char> {
public:
	void func(int t1,char t2)
	{
		std::cout << "class A<int, char>" << std::endl;
	}
};

int main()
{
	A<int, int>().func();
	A<int, char>().func();

	return 0;
}

对于模版参数类型的不同,遇到特化相匹配的类型,会优先匹配优化版本的模版类。

半特化(偏特化)

顾名思义,只特化模版参数的某些参数,一些参数不进行特化。

//原模版
template<typename T1, typename T2>
class A {
public:
	void func()
	{
		std::cout << "class A" << std::endl;
	}
};

//全特化
template<>
class A<int, char> {
public:
	void func()
	{
		std::cout << "class A<int, char>" << std::endl;
	}
};

//半特化(偏特化)
template<typename T1>
class A<T1, char> {
public:
	void func()
	{
		std::cout << "class A<T1, char>" << std::endl;
	}
};

int main()
{
	A<int, int>().func();
	A<int, char>().func();
	A<char, char>().func();

	return 0;
}

 编译器会匹配 类型最为匹配的版本。

参数更进一步的限制

还有一种更为特别的特化,针对指针和引用

//原模版
template<typename T1, typename T2>
class A {
public:
	void func()
	{
		std::cout << "class A" << std::endl;
	}
};

//还有一种特化方式,专门特化指针和引用
template<typename T1, typename T2>
class A<T1*, T2*>
{
public:
	void func()
	{
		std::cout << "class A<T1*, T2*>" << std::endl;
	}
};

template<typename T1, typename T2>
class A<T1&, T2&>
{
public:
	void func()
	{
		std::cout << "class A<T1&, T2&>" << std::endl;
	}
};

template<typename T1, typename T2>
class A<T1*, T2&>
{
public:
	void func()
	{
		std::cout << "class A<T1*, T2&>" << std::endl;
	}
};

template<typename T1, typename T2>
class A<T1, T2&>
{
public:
	void func()
	{
		std::cout << "class A<T1, T2&>" << std::endl;
	}
};

int main()
{
	A<int, int>().func();
	A<int, char>().func();
	A<char, char>().func();
	A<int*, int*>().func();
	A<char&, char&>().func();
	A<char*, char&>().func();
	A<char, char&>().func();

	return 0;
}

  编译器会匹配 类型最为匹配的版本。

猜你喜欢

转载自blog.csdn.net/fengjunziya/article/details/130915474