变量模板和std :: cout - 构造顺序 [英] Variable templates and std::cout -- order of construction

查看:184
本文介绍了变量模板和std :: cout - 构造顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

看起来我们可以安全地使用静态存储持续时间的对象的构造函数中使用 std :: cout 对象问题

It looks like we can safely use std::cout object in constructors of objects with static storage duration as stated in this question.

但是,我不完全确定我们可以安全地使用它们在变量模板的情况下:

However, I'm not entirely sure that we can safely use them in case of variable templates:

#include <iostream>

template<class T>
T x = T{};

void foo()
{
    class Test
    {
    public:
        Test() { std::cout << "Test::Test\n"; }
    };

    Test t = x<Test>;
}


int main()
{
    std::cout << "main\n";
}

此代码在clang中崩溃(

This code crashes in clang (live example) and I'm not sure whether it's a bug or not.

推荐答案

如该问题所述,

#include <iostream>

相当于定义一个全局变量

is the equivalent of defining a global variable

static std::ios_base::Init __init;

(假设您将它包含在TU的开头)保证对于所有静态存储持续时间

which (assuming that you include it at the start of the TU) guarantees that for all static storage duration objects with ordered initialization in the same TU, the stream objects have been set up.

但是,显式和隐式实例化的模板特化具有 >无序初始化( [basic.start.dynamic] / 1 ) 1 :

However, explicitly and implicitly instantiated template specializations have unordered initialization ([basic.start.dynamic]/1)1:


具有静态存储的非本地变量的动态初始化
持续时间是无序的,如果变量是一个隐式或显式的
实例化的特化,否则是有序的[注意省略]。在单个翻译单元中定义的具有有序初始化的变量应当按照它们在翻译单元中的定义的顺序被初始化。

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 omitted]. Variables with ordered initialization defined within a single translation unit shall be initialized in the order of their definitions in the translation unit.

且自


启动一个线程,一个变量的随后的无序初始化
相对于每个其他动态
初始化是不定序的。否则,对于每个其他动态
初始化,变量
的无序初始化不确定地排序。

If a program starts a thread, the subsequent unordered initialization of a variable is unsequenced with respect to every other dynamic initialization. Otherwise, the unordered initialization of a variable is indeterminately sequenced with respect to every other dynamic initialization.

不能保证在对变量模板专用化 x 进行初始化时,流对象已经被初始化。

there's no guarantee that the stream objects have been initialized at the time the variable template specialization x<Test> is initialized.

在这种情况下,由于一个可能的执行导致未定义的行为(在初始化之前使用流对象),整个程序的行为是未定义的(参见 [intro.execution] / 5 )。

In this case, as one of the possible executions results in undefined behavior (using the stream objects before they are initialized), the behavior of the entire program is undefined (see [intro.execution]/5).

修复是构造一个 std :: ios_base :: Init 对象自己在测试的构造函数中。

The fix is to construct a std::ios_base::Init object yourself in Test's constructor.

1 当C ++ 14发布时,这实际上是变量模板的不足,但它始终是目的。

1 This is actually underspecified for variable templates when C++14 was published, but it's always been the intent.

这篇关于变量模板和std :: cout - 构造顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆