C++ 变量模板

一、引入

变量模板是在 C++14 中引入,允许在命名空间范围内定义模板变量(可以表示一组全局变量),或者在类范围内定义模板变量(表示静态数据成员)。

例如:

1
2
template <class T>
constexpr T PI = T(3,1415926535897932385L);

其语法类似于声明变量(或数据成员),但与声明模板的语法相结合。

对于任何模板,该声明不能出现在函数内或者块区域内。

使用变量模板,必须指定它的类型:

1
2
std::cout << PI<double> << '\n';
std::cout << PI<float> << '\n';

二、应用

2.1 简单使用

可以声明在不同编译单元中使用的变量模板:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// =====header.hpp
template<typename T> T val{}; // zero initialized value

// =====translate unit 1:
#include "header.hpp"

int main()
{
val<long> = 42;
print();
}

// =====translate unit 2:
#include "header.hpp"

void print()
{
std::cout << val<long> << '\n'; // OK: print 42
}

2.2 变量模板的显式特化

函数模板 show_parts 会将输入字符串分割为用分隔符分隔的部分后处理。分隔符是在(全局) 命名空间范围内定义的变量模板,并且为 wchar_t 类型显式特化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
template <typename T>
constexpr T SEPARATOR = '\n';

template <>
constexpr wchar_t SEPARATOR<wchar_t> = L'\n';

template <typename T>
std::basic_ostream<T>& show_parts(
std::basic_ostream<T>& s,
std::basic_string_view<T> const& str)
{
using size_type =
typename std::basic_string_view<T>::size_type;
size_type start = 0;
size_type end;

do
{
end = str.find(SEPARATOR<T>, start);
s << '[' << str.substr(start, end - start) << ']'
<< SEPARATOR<T>;
start = end + 1;
} while (end != std::string::npos);

return s;
}

show_parts<char>(std::cout, "one\ntwo\nthree");
show_parts<wchar_t>(std::wcout, L"one line");

2.3 变量模板作为成员变量

变量模板可以是类的成员,可表示静态数据成员,需要使用 static 关键字进行声明:

1
2
3
4
5
6
7
8
9
10
11
struct math_constants
{
template <class T>
static constexpr T PI = T(3.1415926535897932385L);
};

template <typename T>
T sphere_volume(T const r)
{
return 4 * math_constants::PI<T> *r * r * r / 3;
}

可以在类中声明一个变量模板,然后在类外提供它的定义。注意,变量模板必须声明为静态 const,而不是静态constexpr,因为后者需要在类内初始化:

1
2
3
4
5
6
7
8
struct math_constants
{
template <class T>
static constexpr T PI;
};

template <class T>
const T math_constants::PI = T(3.1415926535897932385L);

2.4 简化类型特征

is_integral 为例:

1
2
3
4
5
6
7
template <typename T>
struct is_integral
{
constexpr static bool value = false;
}

std::cout << is_integral<float>::value << '\n';

可以通过如下定义的变量模板来简化:

1
2
3
4
5
template <typename T>
inline constexpr boool is_integral_v =
is_integral<T>::value;

std::cout << is_floating_point_v<float> << '\n';

C++ 变量模板
http://example.com/2026/06/07/C++-变量模板/
作者
Yu xin
发布于
2026年6月7日
许可协议