2009-10-26 9 views
1

Je reçois l'erreur suivante avec le code ci-dessous.Instanciation au niveau global (C++)

expected constructor, destructor, or type conversion before '=' token 

-

#include <string> 
#include <map> 

class Foo { 

}; 

std::map<std::string, Foo> map; 
map["bar"] = Foo(); 

int main() 
{ 

    return 0; 
} 
+2

Votre problème n'est pas "instanciation au niveau global", c'est "essayer d'exécuter une instruction au niveau global". Tu ne peux pas faire ça, désolé. –

Répondre

13
map["bar"] = Foo(); // This line is a statement not a declaration. 
        // You have to put it in main, or any execution context 

Untill C++ 0x devient mainstream, je suggère d'utiliser boost. Remplir le map devient un jeu d'enfant. Voici un exemple:

std::map<std::string, Foo> mymap; 
... 
int main() 
{ 
    insert(mymap) 
    ("First", Foo(...)) 
    ("Second", Foo(...)) 
    ("Third", Foo(...)); 
    ... 
} 
1

Il semble que ce que vous voulez est un initialiseur statique. Je vous suggère de lire this. Son illustration de l'utilisation des initialiseurs statiques et aussi de leur écueil principal, l'ordre d'initialisation statique.

+2

Pourquoi les downvotes? Laissez au moins un commentaire constructif. –

+0

Je ne vous ai pas déprécié, mais je pense que je vois pourquoi la tienne n'est pas une bonne réponse. Cela ne répond pas à la question. L'initialisation statique et les dangers d'ordre peuvent faire partie d'une réponse à sa question, mais vous ne l'avez pas inclus. –

+0

Il n'existe pas d'initialiseur statique en C++. Les globals sont initialisés par leurs constructeurs. Aussi l'article lié est terrible et plein de très mauvais conseils. –

4

La réponse courte, comme vous l'avez vu, est: vous ne pouvez pas faire cela.

Je pense que ce que vous voulez vraiment est la suivante:

std::map<std::string, Foo> map; 

int main() 
{ 
    map["bar"] = Foo(); 

Si vous vraiment besoin de l'initialisation à exécuter avant main() vous souvent voir des exemples comme celui-ci:

namespace { 
    struct StaticInitHelper { 
     StaticInitHelper() { map["bar"] = Foo(); } 
    } _helper_obj; 
} 

Cependant, maintenant vous avez un nouveau problème qui est qu'il n'y a aucune garantie que map est créé avant _helper_obj. Un moyen de contourner cela est de les combiner:

namespace { 
    struct StaticInitHelper : public std::map<std::string, Foo> { 
     StaticInitHelper() { (*this)["bar"] = Foo(); } 
    } map; 
} 

Hériter des classes de conteneur STL n'est généralement pas recommandé. Notez que cet exemple masque tous les autres constructeurs et que la classe de base STL n'a pas de destructeur virtuel. Cela serait considéré comme un "hack" par beaucoup, et devrait vraiment être évité.

Une autre alternative est de définir la classe avec un std::map:

namespace { 
    struct StaticInitHelper { 
     StaticInitHelper() { map["bar"] = Foo(); } 
     std::map<std::string, Foo> map; 
    } map_holder; 
} 

map_holder.map.find(... 

Mais bien sûr, ce qui complique l'utilisation de la carte.

Mise à jour:

j'ai oublié de mentionner une autre option, en utilisant boost::assign:

#include <boost/assign/list_of.hpp> 

map<int,int> map = boost::assign::map_list_of(1,2)(2,3)(3,4)(4,5)(5,6); 

Je ne peux pas trouver des informations sur que ce soit en sécurité sur un objet statique, cependant.

Questions connexes