既然允许C++模板类(class template)的存在,允许C++函数模板(function template)的存在,也应当允许变量模板(variable template)的存在。

变量模板,标准C++14(C++11是C++14的一个subset子集,)的一个新的语法特性。C++新标准引入变量模板的主要目的是为了 简化定义(simplify definitions) 以及对 模板化常量(parameterized constant)的支持

C++14之前的语法规则不允许使用模板声明的方式声明一个变量

template<typename T>
T var;              // not allowed in pre-C++14
var<int> = 5;           // == (int var = 5;)

它足够新,以至于相当多的编译器还未完全支持,比如windows下的vs2013。本文涉及的代码统一在C++的一个在线ide—— ideone 中进行编译(选择这个编译器的目的主要在于它对C++14标准的支持)。


在线编译器c++标准可选
条条大陆通罗马,此路不通(C++14标准之前),我们虽然有一些另外的替代方案,但这些方案,往往冗余度过高且形式比较复杂。

workaround 1

第一种替代方案是,使用类模板的 constexpr static 数据成员的方式:

template<typename T>
struct PI
    constexpr static T pi = T(3.1415926535897932385);
    // 这里必须使用关键字constexpr,而不可以是const
    // const 常量必须在编译器得到确定
    // 自C++11起,constexpr可以让表达式核定于编译期
// duplicate declaration
template<typename T>
constexpr T PI<T>::pi;
int main(int, char**)
    std::cout << PI<int>::pi << std::endl;  
    std::cout << PI<double>::pi << std::endl;   
                                        // 3.14159
    return 0;

这种做法,因为constant是一种ODR(One Definition Rule)的定义规则。对constant的两次声明是有必要的,一次在类模板体内,一次在类模板体外,如上代码所示。

workaround 2

另外一种解决方案是使用constexpr函数模板的形式,该函数返回期待的类型。

template<typename T>
T PI()
    constexpr T pi = T(3.1415926535897932385);
    return pi;
int main(int, char**)
    std::cout << PI<int>() << std::endl;
    std::cout << PI<double>() << std::endl;
    return 0;

variable template

现在,有了C++新标准对变量模板的支持,操纵一个可变类型的常量可以得到显著的简化,

// old version
PI<int>::pi     // constexpr static data member
PI<int>()       // constexpr function
// new version
PI<int>
template<typename T>
constexpr T PI = T(3.1415926535897932385);
template<typename T>
T area(T r)
    return PI<T>*r*r;
int main(int, char**)
    std::cout << PI<int> << std::endl;
    std::cout << area(2.0) << std::endl;    
                // 函数模板的自动类型推导
    return 0;

当然我们亦可以将变量模板应用到一个非常量变量上来;

tempalte<typename T>
T val = T(3.1415926535897932385);
int main(int, char**)
    val<float> = 0.6180339887498948482;
    std::cout << val<float> << std::endl;   
                // 使用新赋的值
    std::cout << val<double> << std::endl;
                // 使用默认值
    return 0;

References

[1] <Introduction to Variable Templates of C++14>

4 struct S { 5 template<typename T> 6 static const T var=0; // declaration of a static data member template 7 }; ...
template用在一个变量上,其目的是什么呢? https://blog.csdn.net/zwvista/article/details/54612025 #include <iostream> #include <iomanip> using namespace std; // 函数模板 template<class T> constexpr T pi_fn() return T(3.1415926535897932385); // 变量模板 templ
如果对模板或者C++标准感兴趣的开发者们相信都不会对变量模板感到陌生,我们今天就讲一讲变量模板C++14 开始,变量也可以被某种类型参数化。称为变量模板。 例如可以通过下面的代码定义pi,但是参数化了其类型: template<typename T=int>//我们写作默认int T pi{};//初始化列表 为0 int main() std::cout.precision(16); pi<int> = 20;//pi<>=20;效果一样
<condition_variable >头文件主要包含有类和函数相关的条件变量。 包括相关类std::condition_variable和std::condition_variable_any,还有枚举类型std::cv_status。另外还包含函数std::notify_all_at_thread_exit(),以下分别介绍一下以上几种类型。 std::condition_variable 类介绍 std::condition_variable是条件变量,很多其它有关条件变量的...
每个模板都可以通过name属性来标识成一个变量模板,而不是通过match属性来匹配具体的元素。然后可以通过来引用变量模板,这样,如果在模板中大量存在相同内容的时候,就可以减少工作量。 可以在变量模板中使用参数来传递内容,具体语法为: bbbbb ………………….. 其中:a为参数名,bbbbb为参数的默认值。 然后在调用模板时传递参数:  ccccc …………………………