2010-08-18 3 views
1

Est-ce portable ou au moins sûr à utiliser avec g ++?C++ l'ordre d'initialisation des globales

#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:

Ok, ce que je dois avéré être un peu plus difficile: le même code avec les modèles:

#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 :-(
} 

Comment pourrais-je résoudre ce problème à travailler comme ci-dessus ?

EDIT 2:

Voici une solution laide avec des macros (je l'espère, il y a une meilleure façon de le faire):

#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 :-) 
} 

(BTW, dois-je ai posté une nouvelle question au lieu des modifications?)

Répondre

0

Pour votre question à jour, je n'ai pas pataugé dans la norme pour savoir quand les membres de modèles implicitement instanciés sont censés être initialisé, mais explicite instanciation ne semble pas être la solution:

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

Standardese à 14.7.2/7:

l'instanciation explicite d'une spécialisation de modèle de classe implique la instanciation de tous ses membres non explicitement spécialisé dans l'unité de traduction contenant le explicite instanciation.

4

Les globaux d'une unité de traduction (correspondant généralement à un fichier .c) sont initialisés dans l'ordre, ce qui est sûr. Vous avez seulement des problèmes, vous avez des globals dans différents fichiers objets qui dépendent les uns des autres.

cela est spécifié dans la norme §3.6.2/2:

variables avec initialisation ordonnée définie à l'intérieur d'une seule unité de traduction doivent être initialisés dans l'ordre de leurs définitions dans l'unité de traduction.

Les variables globales ont une initialisation ordonnée tant qu'elles ne sont pas déclarées static.

+0

Merci d'avoir cherché dans la spécification. Malheureusement, cela ne semble pas s'appliquer aux modèles, comme dans ma question modifiée. – Thomas

2

Commande garantie oui.

Sûr: douteux. Cela dépend de ce que vous voulez dire par sûr.
Mais comme écrit il est portable et ne plantera sur aucun compilateur je sais.