通过示例了解变量模板
Understanding variable templates by example
我试图通过以下示例了解变量模板的工作原理:
#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
}
老实说,我真的不知道那种行为。令我困惑的是特化 var<T, t>
是 0,但 y.a
是 31
。另外,如果我们用临时初始化 T
类型的对象,我们也会得到不同的结果。你能澄清一下吗?
我的意思是,我正在寻找工作草案 N4296
中描述该行为的规范参考。
据推测,var
特化是在其他全局变量之前动态初始化的。在那种情况下,t
需要动态初始化(因为它的初始化器不是常量表达式),因此在用于初始化 var<T, t>
时仍然具有零值;而 tt
可以从其 constexpr
初始化程序静态初始化,因此在用于初始化 var<T, tt>
.
时具有其最终值
但是,我在 draft standard 中找不到任何内容来说明这是否是预期的(如果专业化的声明点是模板本身的声明点),或者 undefined/incorrect 行为。
原因是初始化顺序:
首先是零初始化。所有三个变量都设置为零。
然后是常量初始化。 y
和 tt
使用 constexpr
初始化,产生 31.
动态初始化是最后一个。在此步骤中,编译单元中变量的顺序很重要。 var
在 t
之前,因此 var<T, t>
从 t
初始化,然后 t
从 y
初始化。
目前变量模板还未指定。如果我们遍历 the current core issues list,我们会看到
- It is unclear whether and how a variable template can be defined multiple times in a program.
- It is unclear how definitions and declarations of variable templates are matched.
- It is unclear how variable template partial specializations are supposed to work.
- It is unclear what the point of instantiation of a variable template specialization is.
过去也不清楚变量模板遵循什么初始化顺序。 CWG issue 1744 修改了 [basic.start.init]/p2 以阐明
Dynamic initialization of a non-local variable with static storage
duration is unordered if the variable is an implicitly or
explicitly instantiated specialization, and otherwise is ordered
[Note: an explicitly specialized static data member or variable
template specialization has ordered initialization. —end note].
var<T, t>
是一个具有静态存储持续时间的非局部变量,它是一个隐式实例化的特化。因此它的动态初始化是无序的。由于 t
不符合常量初始化条件,这意味着 var<T, t>
可能会在 t
的动态初始化之前被初始化,结果生成 0,而不管 [=] 之间的相对顺序如何14=] 的定义和 t
的定义,并且与 var<T, t>
.
的实例化点无关
因此,moving the definition of var
below the definition of t
and/or an explicit instantiation of var<T, t>
has no effect on what's being printed, while providing an explicit specialization for var<T, t>
still initializing it to t.a
导致第一行打印 31
。
我试图通过以下示例了解变量模板的工作原理:
#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
}
老实说,我真的不知道那种行为。令我困惑的是特化 var<T, t>
是 0,但 y.a
是 31
。另外,如果我们用临时初始化 T
类型的对象,我们也会得到不同的结果。你能澄清一下吗?
我的意思是,我正在寻找工作草案 N4296
中描述该行为的规范参考。
据推测,var
特化是在其他全局变量之前动态初始化的。在那种情况下,t
需要动态初始化(因为它的初始化器不是常量表达式),因此在用于初始化 var<T, t>
时仍然具有零值;而 tt
可以从其 constexpr
初始化程序静态初始化,因此在用于初始化 var<T, tt>
.
但是,我在 draft standard 中找不到任何内容来说明这是否是预期的(如果专业化的声明点是模板本身的声明点),或者 undefined/incorrect 行为。
原因是初始化顺序:
首先是零初始化。所有三个变量都设置为零。
然后是常量初始化。
y
和tt
使用constexpr
初始化,产生 31.动态初始化是最后一个。在此步骤中,编译单元中变量的顺序很重要。
var
在t
之前,因此var<T, t>
从t
初始化,然后t
从y
初始化。
目前变量模板还未指定。如果我们遍历 the current core issues list,我们会看到
- It is unclear whether and how a variable template can be defined multiple times in a program.
- It is unclear how definitions and declarations of variable templates are matched.
- It is unclear how variable template partial specializations are supposed to work.
- It is unclear what the point of instantiation of a variable template specialization is.
过去也不清楚变量模板遵循什么初始化顺序。 CWG issue 1744 修改了 [basic.start.init]/p2 以阐明
Dynamic initialization of a non-local variable with static storage duration is unordered if the variable is an implicitly or explicitly instantiated specialization, and otherwise is ordered [Note: an explicitly specialized static data member or variable template specialization has ordered initialization. —end note].
var<T, t>
是一个具有静态存储持续时间的非局部变量,它是一个隐式实例化的特化。因此它的动态初始化是无序的。由于 t
不符合常量初始化条件,这意味着 var<T, t>
可能会在 t
的动态初始化之前被初始化,结果生成 0,而不管 [=] 之间的相对顺序如何14=] 的定义和 t
的定义,并且与 var<T, t>
.
因此,moving the definition of var
below the definition of t
and/or an explicit instantiation of var<T, t>
has no effect on what's being printed, while providing an explicit specialization for var<T, t>
still initializing it to t.a
导致第一行打印 31
。