MSVC 2017 нарушает статический порядок инициализации в пределах одного модуля перевода - PullRequest
0 голосов
/ 18 мая 2018

MSVC 2017 Community с -std=c++17 дросселями на следующем примере:

#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 выдает:

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

MSVC дает правильные результаты, если элемент _value удален и пользовательский конструктор отсутствует.

Как все этонаходится в пределах одной единицы перевода, я понимаю, что это подпадает под Частично упорядоченная динамическая инициализация :

2) Частично упорядоченная динамическая инициализация, котораяприменяется ко всем встроенным переменным, которые не являются явно или явно конкретизированной специализацией.Если частично упорядоченный V определен перед упорядоченным или частично упорядоченным W в каждой единице перевода, инициализация V выполняется до инициализации W (или происходит раньше, если программа запускает поток)

Я не могу использовать функцию для обеспечения порядка инициализации, так как мне требуются constexpr значения и constexpr ссылки на них.

Так что вопрос в том, MSVC это в нарушение стандарта * здесь, верно?

* Конечно cppreference.com не является "стандартом", но я предполагаю, что информация там правильно получена.

1 Ответ

0 голосов
/ 18 мая 2018

Я выделяю ту же проблему в этом более простом примере:

#include <iostream>

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

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

, который, используя последнее сообщество MSVC 2017, выдает:

0119D035, 0119D038

Проблема не возникает, если constexpr удаляется.

Так что я думаю, что это ошибка компилятора с constexpr инициализацией ссылкиСсылка была инициализирована &values[0] + 1 байт, а не &values[1], как и должно быть.

NB.Если кто-то не знаком с constexpr ссылочными определениями, см. Здесь или здесь .constexpr указывает, что инициализатор является объектом со статической продолжительностью хранения.

...