Есть ли у gcc какие-либо гарантии относительно статической синхронизации инициализации члена, особенно в отношении классов шаблонов?
Я хочу знать, могу ли я получить твердую гарантию, что статические члены (PWrap_T<T>::p_s
) будут инициализированы до main()
, когда классы создаются через несколько единиц компиляции. Нецелесообразно пытаться вручную коснуться символа из каждой единицы компиляции в начале основного, но мне не ясно, что что-нибудь еще будет работать.
Я тестировал такие методы, как bar()
в разных единицах, и всегда получал желаемый результат, но мне нужно знать, когда/если когда-либо gcc будет вырывать ковер и можно ли его предотвратить.
Кроме того, будут ли инициализированы все статические элементы из 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();
}
(С++ 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
, и я не знаю других трюков относительно статической инициализации.
Заранее благодарим любого, кто может дать мне ответ об этом!