变量模板(C++14 起)

来自cppreference.com
< cpp‎ | language

变量模板定义一族变量或静态数据成员。

语法

template < 形参列表 > 变量声明
变量声明 - 变量的声明。声明的变量名成为模板名。
形参列表 - 非空的模板形参的逗号分隔列表,每项是非类型形参类型形参模板形参,或任何上述的形参包之一。

解释

从变量模板实例化的变量被称为 被实例化变量,从静态数据成员模板实例化的变量被称为 被实例化静态数据成员

变量模板可以通过处于命名空间作用域中的模板声明引入,其中 变量声明 声明一个变量。

template<class T>
constexpr T pi = T(3.1415926535897932385L); // 变量模板
 
template<class T>
T circular_area(T r) // 函数模板
{
    return pi<T> * r * r; // pi<T> 是变量模板实例化
}

在类作用域中使用时,变量模板声明一个静态数据成员模板。

using namespace std::literals;
struct matrix_constants
{
    template<class T>
    using pauli = hermitian_matrix<T, 2>; // 别名模版
 
    template<class T> // 静态数据成员模板
    static constexpr pauli<T> sigmaX = {{0, 1}, { 1, 0 }}; 
 
    template<class T>
    static constexpr pauli<T> sigmaY = {{0, -1i}, {1i, 0}};
 
    template<class T>
    static constexpr pauli<T> sigmaZ = {{1, 0}, {0, -1}};
};

与其他静态成员一样,静态数据成员模板的需要一个定义。这种定义可以在类定义外提供。处于命名空间作用域的静态数据成员的模板声明也可以是类模板的非模板数据成员的定义:

struct limits
{
    template<typename T>
    static const T min; // 静态数据成员模板的声明
};
 
template<typename T>
const T limits::min = {}; // 静态数据成员模板的定义
 
template<class T>
class X
{
    static T s; // 类模板的非模板静态数据成员的声明
};
 
template<class T>
T X<T>::s = 0; // 类模板的非模板静态数据成员的定义

除非变量模板被显式特化或显式实例化,否则在变量模板的特化在要求变量定义存在的语境中被引用,或定义存在与否影响程序语义时,即表达式(可能不使用定义)对常量求值需要该变量时,隐式实例化它。

如果有表达式需要某变量进行常量求值,那么变量定义存在与否会影响程序语义,即使不要求常量求值表达式,或常量表达式求值不使用该定义。

注解

在 C++14 引入变量模板前,参数化变量通常实现为类模板的静态数据成员,或返回所需值的 constexpr 函数模板。

变量模板不能用作模板模板实参

缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

缺陷报告 应用于 出版时的行为 正确行为
CWG 2255 C++14 不明确静态数据成员模板的特化是不是静态数据成员 它是