#c #static-order-fiasco
#c #статический порядок -фиаско
Вопрос:
У меня есть следующие три исходных файла:
main.cc:
#include "constants.h"
#include <cstdlib>
#include <iostream>
template <std::size_t n> class Foo {
public:
static const double bar;
Foo();
};
template <std::size_t n> const double Foo<n>::bar = 4*pi;
template <std::size_t n> Foo<n>::Foo() { std::cout << "ctor: " << bar << std::endl; }
const Foo<42> baz;
int main(void)
{
std::cout << "main(): " << Foo<42>::bar << std::endl;
std::cout << "main(): " << baz.bar << std::endl;
return 0;
}
constants.cc:
#include "constants.h"
const double pi = 3.1415;
constants.h:
#ifndef CONSTANTS_H
#define CONSTANTS_H
extern const double pi;
#endif
и когда я компилирую и связываю все и запускаю исполняемый файл, я получаю:
ctor: 0
main(): 12.566
main(): 12.566
Что дает? Почему конструктор Foo<42> не может видеть правильное значение pi? Похоже, это происходит только в том случае, если Foo является шаблоном, и только если pi определен в другом файле.
Как бы то ни было, я использую g (Ubuntu 7.5.0-3ubuntu1 ~ 18.04) 7.5.0. Все --std={c ,gnu }{98,03,11,14,17}
дают одинаковые результаты.
Спасибо за ваши ответы.
Комментарии:
1. сбой порядка статической инициализации.
2. Исправить это, создав
pi
aconstexpr
? Или используйте вместо этого boost pi (чтобы избежать фиаско).3. Также смотрите эти математические константы доступны в стандартной библиотеке
4. Я думаю, вы столкнулись с «неупорядоченной динамической инициализацией» (см. Здесь ). Существует неожиданный (по крайней мере, для меня) особый случай (т. Е. ошибка, ожидающая своего появления) для инициализации «элементов статических данных шаблона класса […], которые явно не специализированы».
5. Если вы можете использовать c 20, constinit легко решит эту проблему.