Quelle est la bonne façon d'initialiser une carte statique? Avons-nous besoin d'une fonction statique qui l'initialisera?
Utilisation de C++ 11:
#include <map>
using namespace std;
map<int, char> m = {{1, 'a'}, {3, 'b'}, {5, 'c'}, {7, 'd'}};
Utilisation de Boost.Assign :
#include <map>
#include "boost/assign.hpp"
using namespace std;
using namespace boost::assign;
map<int, char> m = map_list_of (1, 'a') (3, 'b') (5, 'c') (7, 'd');
Le meilleur moyen est d'utiliser une fonction:
#include <map>
using namespace std;
map<int,int> create_map()
{
map<int,int> m;
m[1] = 2;
m[3] = 4;
m[5] = 6;
return m;
}
map<int,int> m = create_map();
Ce n'est pas compliqué de créer quelque chose de similaire à stimuler. Voici une classe avec seulement trois fonctions, y compris le constructeur, pour reproduire ce que boost a fait (ou presque).
template <typename T, typename U>
class create_map
{
private:
std::map<T, U> m_map;
public:
create_map(const T& key, const U& val)
{
m_map[key] = val;
}
create_map<T, U>& operator()(const T& key, const U& val)
{
m_map[key] = val;
return *this;
}
operator std::map<T, U>()
{
return m_map;
}
};
Usage:
std :: map mymap = create_map <int, int> (1,2) (3,4) (5,6);
Le code ci-dessus fonctionne mieux pour l'initialisation de variables globales ou de membres statiques d'une classe qui doit être initialisée et vous ne savez pas quand elle sera utilisée pour la première fois, mais vous voulez vous assurer que les valeurs y sont disponibles.
Si par exemple, vous devez insérer des éléments dans un std :: map existant ... voici une autre classe pour vous.
template <typename MapType>
class map_add_values {
private:
MapType mMap;
public:
typedef typename MapType::key_type KeyType;
typedef typename MapType::mapped_type MappedType;
map_add_values(const KeyType& key, const MappedType& val)
{
mMap[key] = val;
}
map_add_values& operator()(const KeyType& key, const MappedType& val) {
mMap[key] = val;
return *this;
}
void to (MapType& map) {
map.insert(mMap.begin(), mMap.end());
}
};
Usage:
typedef std::map<int, int> Int2IntMap;
Int2IntMap testMap;
map_add_values<Int2IntMap>(1,2)(3,4)(5,6).to(testMap);
Voyez-le en action avec GCC 4.7.2 ici: http://ideone.com/3uYJiH
############### TOUT AU-DESSOUS DE CES IS OBSOLETE ############### ##
EDIT: La classe map_add_values
ci-dessous, qui était la solution originale que j'avais suggérée, échouerait pour GCC 4.5+. Veuillez regarder le code ci-dessus pour savoir comment ajouter des valeurs à la carte existante.
template<typename T, typename U>
class map_add_values
{
private:
std::map<T,U>& m_map;
public:
map_add_values(std::map<T, U>& _map):m_map(_map){}
map_add_values& operator()(const T& _key, const U& _val)
{
m_map[key] = val;
return *this;
}
};
Usage:
std :: map <int, int> my_map; // quelque part ultérieurement dans le code map_add_values <int, int> (my_map) (1,2) (3,4) (5, 6);
REMARQUE: Auparavant, j’utilisais un operator []
pour ajouter les valeurs réelles. Ce n'est pas possible comme l'a commenté dalle.
###################### FIN DE LA SECTION OBSOLÈLE ############### #####
Voici un autre moyen qui utilise le constructeur de données à 2 éléments. Aucune fonction n'est nécessaire pour l'initialiser. Il n'y a pas de code tiers (Boost), pas de fonctions ni d'objets statiques, pas de trucs, juste du C++ simple:
#include <map>
#include <string>
typedef std::map<std::string, int> MyMap;
const MyMap::value_type rawData[] = {
MyMap::value_type("hello", 42),
MyMap::value_type("world", 88),
};
const int numElems = sizeof rawData / sizeof rawData[0];
MyMap myMap(rawData, rawData + numElems);
Depuis que j'ai écrit cette réponse, C++ 11 est sorti. Vous pouvez maintenant initialiser directement les conteneurs STL à l'aide de la nouvelle fonctionnalité de liste d'initialisation:
const MyMap myMap = { {"hello", 42}, {"world", 88} };
Je voudrais envelopper la carte dans un objet statique et mettre le code d'initialisation de la carte dans le constructeur de cet objet, de cette façon, vous êtes sûr que la carte est créée avant l'exécution du code d'initialisation.
Par exemple:
const std::map<LoggerLevel, const char*> g_logLevelsDescriptions =
{
{ LoggerLevel::llNothing, "Logging disabled" },
{ LoggerLevel::llInfo, "Base information" },
{ LoggerLevel::llWarn, "Warnings" },
{ LoggerLevel::llError, "Errors" },
{ LoggerLevel::llDebug, "All information: debug-mode" }
};
Je voulais juste partager un pur travail C++ 98 autour de:
#include <map>
std::map<std::string, std::string> aka;
struct akaInit
{
akaInit()
{
aka[ "George" ] = "John";
aka[ "Joe" ] = "Al";
aka[ "Phil" ] = "Sue";
aka[ "Smitty" ] = "Yando";
}
} AkaInit;
Tu peux essayer:
std::map <int, int> mymap =
{
std::pair <int, int> (1, 1),
std::pair <int, int> (2, 2),
std::pair <int, int> (2, 2)
};
Ceci est similaire à PierreBdR
, sans copier la carte.
#include <map>
using namespace std;
bool create_map(map<int,int> &m)
{
m[1] = 2;
m[3] = 4;
m[5] = 6;
return true;
}
static map<int,int> m;
static bool _dummy = create_map (m);
Si vous êtes coincé avec C++ 98 et que vous ne voulez pas utiliser le boost, voici la solution que j'utilise lorsque je dois initialiser une carte statique:
typedef std::pair< int, char > elemPair_t;
elemPair_t elemPairs[] =
{
elemPair_t( 1, 'a'),
elemPair_t( 3, 'b' ),
elemPair_t( 5, 'c' ),
elemPair_t( 7, 'd' )
};
const std::map< int, char > myMap( &elemPairs[ 0 ], &elemPairs[ sizeof( elemPairs ) / sizeof( elemPairs[ 0 ] ) ] );