MSVC 2017违反了单个翻译单元中的静态初始化顺序 [英] MSVC 2017 violating static initialization order within single translation unit

查看:114
本文介绍了MSVC 2017违反了单个翻译单元中的静态初始化顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

MSVC 2017社区受到了-std=c++17的阻碍:

MSVC 2017 Community with -std=c++17 chokes on the following example:

#include <iostream>

struct TC
{
    static TC const values[];
    static TC const& A;
    static TC const& B;
    static TC const& C;

    int const _value;
};

inline constexpr TC const TC::values[]{ { 42 }, { 43 }, { 44 } };
inline constexpr TC const& TC::A{ values[0U] };
inline constexpr TC const& TC::B{ values[1U] };
inline constexpr TC const& TC::C{ values[2U] };

int main(int, char**) noexcept
{
    std::cout << std::boolalpha
        << "&A == &values[0]? " << (&TC::A == &TC::values[0U]) << "\n" 
        << "&B == &values[1]? " << (&TC::B == &TC::values[1U]) << "\n"
        << "&C == &values[2]? " << (&TC::C == &TC::values[2U]) << "\n";
    return 0;
}

预期的输出为:

&A == &values[0]? true
&B == &values[1]? true
&C == &values[2]? true

gcc和clang都产生了什么,但是MSVC提供了:

Which is what both gcc and clang produce, but MSVC gives:

&A == &values[0]? true
&B == &values[1]? false
&C == &values[2]? false

如果删除_value成员并且没有用户定义的构造函数,则

MSVC确实会给出正确的结果.

MSVC does give the correct results if the _value member is removed and there is no user-defined constructor.

由于所有这些都在一个翻译单元中,因此我的理解是,这属于 部分排序的动态初始化 :

As all of this is within a single translation unit, my understanding is that this falls under Partially-ordered dynamic initialization:

2)部分排序的动态初始化,适用于所有 不是隐式或显式实例化的内联变量 专业化.如果在订购前定义了部分订购的V或 在每个翻译单元中部分排序的W,V的初始化 在W初始化之前进行排序(或在-之前发生,如果 程序启动一个线程)

2) Partially-ordered dynamic initialization, which applies to all inline variables that are not an implicitly or explicitly instantiated specialization. If a partially-ordered V is defined before ordered or partially-ordered W in every translation unit, the initialization of V is sequenced before the initialization of W (or happens-before, if the program starts a thread)

我无法使用函数来确保初始化顺序,因为我需要constexpr constexpr引用它们.

I cannot use a function to ensure initialization order as I require constexpr values and constexpr references to them.

问题是,这里的MSVC 违反了标准*,对吗?

So the question is, MSVC is in violation of the standard* here, correct?

*当然 cppreference.com 不是标准",但我假设其中的信息是正确来源的.

*Of course cppreference.com isn't "the standard", but I'm assuming that the information there is correctly sourced.

推荐答案

我将相同的问题隔离到这个简单的示例中:

I isolate the same problem to this simpler example:

#include <iostream>

int values[3];
constexpr int& v{ values[1] };

int main()
{
    std::cout << &v << ", " << &values[1] << "\n";
    return 0;
}

使用最新的MSVC 2017社区,其输出为:

which, using latest MSVC 2017 Community, gives output of:

0119D035, 0119D038

如果删除了constexpr,则不会发生此问题.

The problem does not happen if constexpr is removed.

所以我认为这是带有constexpr参考初始化的编译器错误.该引用已初始化为&values[0] + 1个字节,而不是应为的&values[1].

So I think this is a compiler bug with constexpr reference initialization. The reference was initialized to &values[0] + 1 byte, not &values[1] as it should be.

NB.如果不熟悉constexpr参考定义,请请参见此处

NB. If anyone is not familiar with constexpr reference definitions, see here or here. constexpr enforces that the initializer is an object with static storage duration.

这篇关于MSVC 2017违反了单个翻译单元中的静态初始化顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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