Bootstrap

【变量模板】变量模板与成员函数

一、变量模板

1.变量模板的使用

变量模板的英文名为 V a r i a b l e   T e m p l a t e Variable \ Template Variable Template,是C++14引入的新标准。
一般这种变量模板需要定义在全局空间或者命名空间中
代码如下:

//变量模板
template<typename T>
T g_myvar {};

这里定义了一个 g m y v a r g_myvar gmyvar的类型模板,初始话为空,这里补充一些空初始化的方法,一下四种都是合法的。

T g_myvar = 0;
T g_my_var = {}
T g_my_var {}
T g_my_var ()

通常情况下,空初始化中 i n t int int赋值为 0 0 0 b o o l bool bool类型赋值为 f a l s e false false
下面是变量模板的一般使用:

void Test(){
	g_myvar<int> = 10; //int类型的变量模版
	std::cout << g_myvar<int> << "\n";
	
	g_myvar<float> = 1.0f;
	std::cout << g_myvar<float> << "\n"; //float类型的变量模板

}

可以理解为,变量模板的类型在 < > <> <>里面,前面是类型名。在 g _ m y v a r < i n t > g\_myvar<int> g_myvar<int>中,相当于 g m y v a r g_myvar gmyvar是类型名, < i n t > <int> <int>为变量类型。

2.变量模板的特化

变量模板和普通模板一样,能够特化。这里实现一下变量模板的特化,代码如下所示:

//泛化
template<typename T>
T my_var{};

//全特化
template<>
char my_var<double> {};  

//偏特化 参数类型的特化
template<typename T>
T my_var<T*> {100}; //初始值

在这里面,我们实现的偏特化和全特化。
下面是全特化的使用:
虽然看上去很奇怪,但是这样的确是合法,这里的 < d o u b l e > <double> <double>类型实际上只是特化版本的推导符,推导出 c h a r char char类型的变量模板。

void Test2() {
	my_var <double> = 'a';

	std::cout << my_var<double> << "\n";
}

下面是偏特化版本变量模板:
和全特化版本类似,这里的 < i n t ∗ > <int*> <int>也只是一个推导符,实际上存储的还是 i n t int int类型。在这里前者将调用泛化版本,后者将调用偏特化版本的模板。

注意的是,偏特化版本的参数必须依赖变量模板的类型,比如这里的 T T T T ∗ T* T

void Test3() {
	std::cout << my_var<int> << "\n"; //调用泛化版本
	std::cout << my_var<int*> << "\n";//调用偏特化版本

}

3.默认模板参数

下面的代码使用了默认参数,在调用的时候可以不写参数,使用默认参数:

//默认模板参数
template<typename T = int>
T my_var2 {20};

void Test4() {
	std::cout << my_var2<int> << "\n";
	
	std::cout << my_var2<> << "\n"; //使用默认参数
}

4.非类型模板参数

在模板参数中也可以传入非类型模板参数。
以下的代码就实现了一个变量模板的数组:

//非类型模板参数
template<typename T,size_t value> 
T my_var3[value];

void Test5() {
	//定义一个数组,大小为15
	for (int i = 0; i < 15; ++i) {
		my_var3<int,15>[i] = i;
	}

	for (int i = 0; i < 15; ++i) {
		std::cout << my_var3<int, 15>[i] << " ";
	}
	std::cout << "\n";

}

5. 变量模板的另一种形式

变量模板还能通过构造类模板中的静态类型模板来实现。
具体而言如下:

//变量模板的另一种形式
template<typename T>
struct B {
	const static T value = { 160 }; 
};

//变量模板的使用
template<typename T>
int my_var4 = B<int>::value; //静态成员函数

我们在类外定义了一个变量模板,名称为 m y _ v a r 4 my\_var4 my_var4。这里的变量模板是基于类中的静态变量模板。

具体使用如下:
注意修改变量模板的值并不会影响类内的静态成员变量:


void Test6() {
	std::cout << my_var4<int> << "\n";
	
	my_var4<int> = 150;
	std::cout << my_var4<int> << "\n";

	std::cout << B<int>::value << "\n"; //这里仍然是160,因为是静态函数
}

二、成员变量模板

成员变量模板也是基于静态成员变量的模板。注意的是,静态成员变量需要再类内声明,类外定义,如下代码所示:

//成员变量模板
template<typename T>
class D {
public:
	template<typename W>
	static W m_tpi; //静态成员变量声明

};

template<typename T>
template<typename W>
W D<T>::m_tpi = 5; //静态成员变量定义

在使用的时候,需要先指定类模板中的类模板的类型,然后再指定静态成员变量的类型(也就是成员变量模板类型)

具体使用如下所示:

void Test7() {
	std::cout << D<float>::m_tpi<int> << "\n"; //5
	D<float>::m_tpi<int> = 150;
	std::cout << D <float>::m_tpi<int> << "\n"; //150
}
;