40 votes

C ++, puis-je initialiser statiquement une carte std :: map au moment de la compilation?

Si j'ai ce code

std::map<int, char> example = { (1,'a'),
                            (2, 'b'),
                            (3, 'c') };

alors g++ me dit

deducing from brace-enclosed initializer list requires #include <initializer_list>
in C++98 ‘example' must be initialized by constructor, not by ‘{...}'   

et qui m'agace légèrement parce que le constructeur est exécuté en temps et peut, en théorie échouer.

Bien sûr, si il ne, il ne sera pas rapidement et doit le faire de manière cohérente, de sorte que je dois localiser rapidement & corriger le problème.

Mais, tout de même, je suis curieux de savoir est - il de toute façon à initialiser la carte, vecteur, etc, au moment de la compilation?


Edit: j'aurais dû dire que je suis en train d'élaborer pour les systèmes embarqués. Pas tous les processeurs ont un compilateur C++0x. Le plus populaire sera probablement, mais je ne veux pas à la rencontre d'une chasse aux sorcières ' et de maintenir 2 de la version s du code.

De coup de pouce, je suis indécis. Ils sont fade sur l'utilisation de leur Machine à états Finis classes de systèmes embarqués, de sorte que c'est effectivement ce que je suis codage ici, d'Événement/État/Fsm classes.

Soupir, je suppose que je ferais mieux de simplement jouer la sécurité, mais j'espère que cette discussion a été utile pour les autres.

37voto

Dmitry Points 3946

Ce n'est pas exactement l'initialisation statique, mais essayez-le. Si votre compilateur ne prend pas en charge C ++ 0x, je choisirais le constructeur d'itération de std :: map:

 std::pair<int, std::string> map_data[] = {
    std::make_pair(1, "a"),
    std::make_pair(2, "b"),
    std::make_pair(3, "c")
};

std::map<int, std::string> my_map(map_data,
    map_data + sizeof map_data / sizeof map_data[0]);
 

C'est assez lisible, ne nécessite aucune bibliothèque supplémentaire et devrait fonctionner dans tous les compilateurs.

21voto

Artyom Points 17387

Pas en C ++98. C ++0x prend en charge cela, donc si vous activez les drapeaux C ++0x et incluez ce que g ++ suggère, vous pouvez.

14voto

mloskot Points 13971

Vous pouvez utiliser la bibliothèque Boost.Assign :

 #include <boost/assign.hpp>
#include <map>
int main()
{
   std::map<int, char> example = 
      boost::assign::map_list_of(1, 'a') (2, 'b') (3, 'c');
}
 

Cependant, comme Neil et d'autres l'ont souligné dans les commentaires ci-dessous, cette initialisation se produit lors de l'exécution, de manière similaire à la proposition d'UncleBean.

13voto

UncleBens Points 24580

Avec C++0x vous pourriez avoir besoin d'utiliser des accolades tout le chemin (utiliser la nouvelle syntaxe de style pour chaque paire en tant que bien):

std::map<int, char> example = { {1,'a'}, {2, 'b'}, {3, 'c'} };

Ces crochets pour construire les paires ne sont pas significatives. Sinon, vous pouvez pleinement nom de chaque paire ou de l'utilisation make_pair (comme vous le feriez en C++98)

std::map<int, char> example = {
    std::make_pair(1,'a'),
    std::make_pair(2, 'b'),
    std::make_pair(3, 'c')
};

Comme pour la création de ces instances au moment de la compilation: non. Des conteneurs STL tous les encapsuler entièrement la mémoire d'exécution de la gestion.

Je suppose, vous ne vraiment avoir un moment de la compilation de la carte avec des bibliothèques comme boost de la métaprogrammation (pas sûr à 100%, si elle est tout à fait correct, et je n'ai pas étudié ce que ça pourrait être bon pour):

using namespace boost::mpl;
map<
    pair<integral_c<int, 1>, integral_c<char, 'a'> >,
    pair<integral_c<int, 2>, integral_c<char, 'b'> >,
    pair<integral_c<int, 3>, integral_c<char, 'c'> >
> compile_time_map;

4voto

Georg Fritzsche Points 59185

Avec pré-C++0x, la chose la plus proche que vous pouvez obtenir est de ne pas utiliser des récipients conçus pour l'exécution d'utilisation (et de te limiter aux types fondamentaux et les agrégats):

struct pair { int first; char second; };
pair arr[] = {{1,'a'}, {2,'b'}}; // assuming arr has static storage

Cela pourrait alors être consulté en utilisant une sorte de vue de la carte, ou vous pouvez mettre en œuvre un wrapper qui permet pour l'ensemble de l'initialisation de semblable à ce coup de pouce.Tableau fait.

Bien sûr, la question est de savoir si les avantages de justifier le temps pour mettre en œuvre cette.

Si ma lecture est correcte ici, C++0x initialiseur-les listes peuvent vous donner initialisation statique de non-agrégats comme std::map et std::pair, mais seulement si cela ne change pas la sémantique par rapport à la dynamique de l'initialisation.
Ainsi, il me semble que vous ne pouvez obtenir ce que vous avez demandé si votre application peut vérifier par l'analyse statique que le comportement ne change pas si l' map est initialisé de manière statique, mais aucune garantie que ça se passe.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X