为什么此循环模板实例合法?

单打

我不明白编译器在这里做什么:

#include <iostream>
using namespace std;

// non-default-constructable struct
struct X
{
    X(int v) : x(v) {}
    const int x;
};

template< typename T>
struct A
{
    static const X a;
};

// trigger a compiler error if we try to instantiate the default template
template< typename T >
const X A<T>::a;


template<>
struct A<int>
{
    static const X a;
};

template<>
struct A<float>
{
    static const X a;
};

// is this not infinitely circular?
const X A<int>::a = X(A<float>::a.x + 1);
const X A<float>::a = X(A<int>::a.x + 1);

int main() {
    // error as expected, A<bool>::a cannot be default-constructed
    // cout << A<bool>::a.x << endl; 

    // this compiles and prints "1 2"
    cout << A<int>::a.x << " " << A<float>::a.x << endl;
    return 0;
}

我本来希望这两个专门的定义a会产生编译器错误,因为它们都使用另一个的值进行了初始化,甚至没有默认构造函数可以使用。但是显然,这可以用ideone进行打印1 2那么,编译器如何得出结论,X应使用这些值初始化的两个实例

Serge Ballesta

这恰好是非局部变量初始化的副作用。该标准说:

3.6.2非局部变量的初始化[basic.start.init]

……
在进行任何其他初始化之前,应将具有静态存储持续时间(3.7.1)或线程存储持续时间(3.7.2)的变量初始化为零(8.5)
。在进行任何动态初始化之前。如果变量是隐式或显式实例化的特殊化,则动态地初始化具有静态存储持续时间的非局部变量是无序的,否则是有序的[注意:显式专用的静态数据成员或变量模板的特殊化已对初始化进行了排序。—尾注]在单个转换单元中定义了有序初始化的变量应按其在转换单元中的定义顺序进行初始化。

这就是这里发生的情况:

  • A<int>::a并且A<float>::a都初始化为0
  • 然后按照定义的顺序对其进行初始化
    • 首先A<int>::a读取A<float>::a由于先前的0初始化而其中为0的内容,然后加1并用1完全初始化
    • 然后A<float>::a获取现在完全初始化的A<int>::a值为1,加1并用2完全初始化

这意味着这是一个格式正确的程序。

但同一段后来说:

如果对象obj1的初始化引用了可能需要动态初始化并在以后在同一转换单元中定义的命名空间范围的对象obj2,则未指定使用的obj2的值是否将是完全初始化的obj2的值(因为obj2为静态初始化)或将只是零初始化的obj2的值

所以我不确定如果A<int>::afirst的动态初始化触发的动态初始化,则输出是否需要为1 2,或者是否可以为2,1 A<float>::a

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

模板实例化绑定在什么时候发生?

constexpr函数失败的模板实例化

为什么以下代码导致模板实例化?

模板实例化

为什么在一个实例中跳过此js循环?

为什么C ++函数模板实例化的返回类型包含在错误的函数名称中?

显式模板实例化

为什么此循环不循环?

模板实例化歧义

为什么不使用模板实现新功能?

为什么只在共享库中导出其中一些C ++模板实例化?

为什么显式模板实例化不会破坏ODR?

部分模板实例化

当存在离线虚拟时,为什么显式模板实例化会导致弱模板vtables警告?

C ++为什么“注意:请参见对正在编译的类模板实例化的引用”

为什么在模板实例化中不允许使用lambda?

为什么此适用实例不合法?

通过typedef template <typename T,T>强制模板实例化-为什么有效?

为什么要使用继承和多态性而不是函数模板实例来调用具有相同签名的成员函数?

通知格式错误的模板实例的最佳方法是什么?

为什么C ++模板实例化失败?

为什么太空飞船允许混合比较(不同的模板实例化)和无意义的结果?

多个文件中的模板实例化

为什么将struct与可变参数template参数一起使用会同时使两个模板实例化?

为什么必须将类模板实例化为完全对象类型?

为什么模板实例化在这里永远存在?

为什么我的可变参数模板实例化不起作用?

为什么在使用带有 decltype 的尾随返回类型调用同名函数时,模板实例化中会发生无限递归?

递归模板实例化在 dtor 中超出错误,但在 ctor 中没有。为什么?