一、变量模板
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
}