通过示例了解变量模板

时间:2015-02-09 17:15:33

标签: 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
}

DEMO

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

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

3 个答案:

答案 0 :(得分:9)

目前,变量模板尚未明确。如果我们通过the current core issues list,我们会看到

以前还不清楚初始化顺序变量模板的后续内容。 CWG issue 1744修改了[basic.start.init] / p2以澄清

  

使用静态存储动态初始化非局部变量   如果变量是隐式或者,则duration unordered   显式实例化特化,否则有序   [注意:明确专门的静态数据成员或变量   模板特化已订购初始化。 - 结束记录]。

var<T, t>是一个非局部变量,其静态存储持续时间是隐式实例化的特化。因此,它的动态初始化是无序的。由于t没有资格进行常量初始化,这意味着可以在var<T, t>的动态初始化之前初始化t,结果产生0,无论两者之间的相对顺序如何var的定义和t的定义,无论var<T, t>的实例化点如何。

因此,moving the definition of var below the definition of t和/或an explicit instantiation of var<T, t>对正在打印的内容没有影响,而providing an explicit specialization for var<T, t> still initializing it to t.a会导致第一行打印31

答案 1 :(得分:3)

原因是初始化顺序:

  • 首先是零初始化。所有三个变量都设置为零。

  • 然后是常量初始化。使用y初始化ttconstexpr,结果为31。

  • 动态初始化是最后一个。在此步骤中,编译单元中变量的顺序很重要。 var位于t之前,因此var<T, t>t初始化t之前初始化y

答案 2 :(得分:2)

据推测,var特化是在其他全局变量之前动态初始化的。在这种情况下,t需要动态初始化(因为它的初始化不是常量表达式),因此在用于初始化var<T, t>时仍然具有零值;虽然tt可以从其constexpr初始化程序进行静态初始化,但在用于初始化var<T, tt>时也是如此。

但是,我在draft standard中找不到任何内容来说明这是否是预期的(因为如果专业化的声明点是模板本身的那一点),或未定义/不正确的行为