变量模板
本节将介绍 C++14 变量模板
初识变量模板
变量模板不是变量,只有实例化的变量模板,编译器才会生成实际的变量。
变量模板实例化后简单的说 就是一个全局变量 ,所以也不用担心生存期的问题。
定义变量模板
就这么简单,毫无难度。
当然了,既然是变量,自然可以有各种的修饰,比如 cv 限定,比如
constexpr
,当然也可以有初始化器,比如
{}
、
= xxx
。
使用变量模板
我们知道
constexpr
附带了
const
类型,所以其实:
std::is_same_v 其实也是个变量模板,在 C++17 引入。这里用来比较两个类型是否相同,如果相同返回 1,不相同返回 0。暂时不用纠结它是如何实现的,后续会手搓。
会打印 1,也就是
v<int>
的类型其实就是
const int
。
我们再提出一个问题,
v<int>
和
v<double>
有什么关系吗?
最早在函数模板中,我们强调了“ 同一个函数模板生成的不同类型的函数,彼此之间没有任何关系 ”,这句话放在类模板、变量模板中,也同样适用。
以上示例打印的地址不会相同。
有默认实参的模板形参
变量模板和函数模板、类模板一样,支持模板形参有默认实参。
与函数模板和类模板不同,即使模板形参有默认实参,依然要求写明
<>
。
非类型模板形参
变量模板和函数模板、类模板一样,支持非类型模板形参。
当然,它也可以有默认值:
可变参数变量模板
变量模板和函数模板、类模板一样,支持形参包与包展开。
array 是一个数组,我们传入的模板实参用来推导出这个数组的大小以及初始化。
{values...}
展开就是
{1, 2, 3, 4, 5}
。
在 msvc 与 gcc14 会输出
1
,但是 gcc14 之前的版本、clang,却会
输出
0
。
msvc 与 gcc14 是正确的
。 gcc 与 clang 不认为
array<1, 2, 3, 4, 5>
与
const std::size_t[5]
类型相同;它们认为
array<1, 2, 3, 4, 5>
与
const std::size_t[]
类型相同
,这显然是个
bug
。
可以参见 llvm issues .
类静态数据成员模板
在类中也可以使用变量模板。
类静态数据成员
讲模板之前先普及一下静态数据成员的基本知识,因为 网上很多资料都是乱讲 ,所以有必要重复强调一下。
n 是一个 X 类的静态数据成员,它在 X 中声明,但是却没有定义,我们需要类外定义。
或者在 C++17 以 inline 或者 constexpr 修饰。
因为 C++17 规定了 inline 修饰静态数据成员,那么这就是在类内定义,不再需要类外定义。constexpr 在 C++17 修饰静态数据成员的时候,蕴含了 inline 。
模板
与其他静态成员一样,静态数据成员模板的需要一个定义。