Имеет ли gcc какие-либо гарантии относительно статического времени инициализации члена, особенно в отношении классов шаблонов?Инициализация статического члена без отсрочки для шаблонов в gcc?
Я хочу знать, могу ли я получить твердую гарантию, что статические члены (PWrap_T<T>::p_s
) будут инициализированы до main()
, когда классы создаются через несколько единиц компиляции. Нецелесообразно пытаться вручную коснуться символа из каждой единицы компиляции в начале основного, но мне не ясно, что что-нибудь еще будет работать.
Я проверил с методами, как bar()
в различных единицах измерения и всегда получили желаемый результат, но мне нужно знать, когда/если когда-либо НКУ будет дергать ковер, и является ли это предотвратить.
Кроме того, будут ли инициализированы все статические элементы от DSO до того, как библиотека завершит загрузку?
#include <iostream>
#include <deque>
struct P;
inline std::deque<P *> &ps() { static std::deque<P *> d; return d; }
void dump();
struct P {
P(int id, char const *i) : id_(id), inf_(i) { ps().push_back(this); }
void doStuff() { std::cout << id_ << " (" << inf_ << ")" << std::endl; }
int const id_;
char const *const inf_;
};
template <class T>
struct PWrap_T { static P p_s; };
// *** Can I guarantee this is done before main()? ***
template <class T>
P PWrap_T<T>::p_s(T::id(), T::desc());
#define PP(ID, DESC, NAME) /* semicolon must follow! */ \
struct ppdef_##NAME { \
constexpr static int id() { return ID; } \
constexpr static char const *desc() { return DESC; } \
}; \
PWrap_T<ppdef_##NAME> const NAME
// In a compilation unit apart from the template/macro header.
void dump() {
std::cout << "[";
for (P *pp : ps()) { std::cout << " " << pp->id_ << ":" << pp->inf_; }
std::cout << " ]" << std::endl;
}
// In some compilation unit.
void bar(int cnt) {
for (int i = 0; i < cnt; ++i) {
PP(2, "description", pp);
pp.p_s.doStuff();
}
}
int main() {
dump();
PP(3, "another", pp2);
bar(5);
pp2.p_s.doStuff();
}
(C++ 11 §3.6.2/4 - [basic.start.init] :)
Она определяется реализацией ли динамическая инициализация не локальное переменная со статической продолжительностью хранения выполняется до первого утверждения main. Если инициализация отложена до некоторого момента времени после первого утверждения main, она должна произойти до первого использования odr (3.2) любой функции или переменной, определенной в той же самой единицы перевода, что и переменная, подлежащая инициализации.
... Нелинейная переменная со статической продолжительностью хранения, имеющей инициализацию с побочными эффектами, должна быть инициализирована, даже если она не используется odr (3.2, 3.7.1).
Кроме того, пытаясь __attribute__ ((init_priority(int)))
или __attribute__ ((constructor))
для инициализации члена шаблона дали warning: attributes after parenthesized initializer ignored
, и я не знаю никаких других уловок относительно статической инициализации.
Заранее благодарим всех, кто может дать мне ответ об этом!
я себе 'правило ODR-use' предназначен для покрытия динамических разделяемых объектов (DSO,), которые могут иметь объекты файловой области видимости. Вы, очевидно, не можете инициализировать все в DSO, если он появился после основных запусков 'dlopen()', но теоретически 'dlopen()' может гарантировать, что все в DSO инициализируется, прежде чем вы вызовете что-нибудь еще в DSO. Я полагаю, что ответ в конечном итоге определяется ABI для любой OS/архитектуры, которую вы компилируете. –
Одноэлементный шаблон решает проблему, не так ли? – lkanab