通过示例了解变量模板

16 c++ templates c++14

我试图通过以下示例了解变量模板的工作原理:

#include <iostream>

template <class T, const T& t>
int var = t.a;

struct T
{
    int a;
    constexpr T(): a(31){ }
};

T y;

const T t = y;

const T tt = T();

int main()
{ 
    std::cout << "var <T, t> = " << var<T, t> << std::endl;  //0
    std::cout << "y.a = " << y.a << std::endl;  //31
    std::cout <<"var <T, tt> = " << var<T, tt> << std::endl; //31
}
Run Code Online (Sandbox Code Playgroud)

DEMO

老实说,我真的不知道这种行为.这让我感到困惑的事情是,专业化var<T, t>为0,但y.a31.另外,如果我们T用临时初始化类型的对象,我们也会有不同的结果.你能澄清一下吗?

我的意思是,我正在寻找工作草案的规范性参考N4296,描述这种行为.

T.C*_*.C. 9

目前,变量模板尚未明确规定.如果我们浏览当前的核心问题列表,我们就会看到

它还不清楚初始化顺序变量模板遵循的是什么.CWG问题1744修改了[basic.start.init]/p2以澄清这一点

如果变量是隐式或显式实例化的特化,则静态存储持续时间的非局部变量的动态初始化是 无序的,否则是有序的 [ 注意:显式专用的静态数据成员或变量模板特化已经有序初始化.- 结束说明 ].

var<T, t>是一个非局部变量,具有静态存储持续时间,是一个隐式实例化的特化.因此,它的动态初始化是无序的.由于t不符合常量初始化的要求,这意味着var<T, t>可以在动态初始化之前初始化t,因此产生0,无论var定义和t定义之间的相对顺序如何,并且无论实例化的点如何var<T, t>.

因此,移动定义var下面的定义t和/或显式实例化对var<T, t>正在打印的内容没有影响,同时提供var<T, t>仍然初始化它的明确专门化以t.a使第一行打印31.