c ++ порядок инициализации глобалов - PullRequest
1 голос
/ 18 августа 2010

Это портативный или хотя бы безопасный для использования с g ++?

#include <iostream>
#include <vector>

struct c {};
std::vector<c*> v;
struct i : c { i () { v.push_back (this); } } a, b, c;

int main () {
  std::cout << v.size () << "\n"; // outputs 3 with g++
}

EDIT:

Хорошо, то, что мне нужно, оказалось немного сложнее: тот же код с шаблонами:

#include <iostream>
#include <vector>

template < typename T > struct c {};
template < typename T > struct cv { static std::vector<c<T>*> v; };
template < typename T > std::vector<c<T>*> cv<T>::v;
template < typename T > struct i : c<T> { i () { cv<T>::v.push_back (this); } };

cv<int> dummy; // even this won't initialize cv<int>::v
i<int> a, b, d;

int main () {
  std::cout << cv<int>::v.size () << "\n"; // outputs 0 :-(
}

Как я могу исправить это, чтобы работать как указано выше?

РЕДАКТИРОВАТЬ 2:

Вот некрасивое исправление с макросами (надеюсь, есть лучший способ сделать это):

#include <iostream>
#include <vector>

template < typename T > struct c {};
template < typename T > struct cv;
#define INITCV(X) \
  struct v##X { static std::vector<c<X>*> v; }; \
  std::vector<c<X>*> v##X::v; \
  template <> struct cv<X> { typedef v##X V; }
template < typename T > struct i : c<T> { i () { cv<T>::V::v.push_back (this); } };

INITCV(int);
i<int> a, b, d;

int main () {
  std::cout << cv<int>::V::v.size () << "\n"; // outputs 3 again :-)
}

(Кстати, я должен был опубликовать новый вопрос вместо изменений?)

Ответы [ 3 ]

4 голосов
/ 18 августа 2010

Глобалы в единице перевода (обычно это файл .c) инициализируются по порядку, поэтому это безопасно. Проблемы возникают только в том случае, если у вас есть глобальные переменные в разных объектных файлах, которые зависят друг от друга.

Это указано в стандарте в §3.6.2 / 2 :

Переменные с упорядоченной инициализацией, определенной в одной единице перевода, должны быть инициализированы в порядке их определений в единице перевода.

Глобальные переменные имеют упорядоченную инициализацию, если они не объявлены static.

2 голосов
/ 18 августа 2010

Заказ гарантированно да.

Сейф: сомнительный. Зависит от того, что вы подразумеваете под сейфом.
Но, как написано, он переносим и не будет зависать ни на одном из известных мне компиляторов.

0 голосов
/ 18 августа 2010

Что касается вашего обновленного вопроса, я не пробежался по стандарту, чтобы выяснить, когда члены неявно-инстанцированных шаблонов должны быть инициализированы, но явное создание экземпляров действительно кажется решением:

template class cv<int>; // Not a dummy. Declares the template like a class.

Стандарт на 14.7.2 / 7:

Явная реализация класса специализация шаблона подразумевает создание экземпляров всех его членов ранее явно не специализированный в блоке перевода, содержащем явная реализация.

...