Réponses:
En utilisant 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();
extern
les variables n'auront pas leurs valeurs correctes dans ce «avant le constructeur principal» si le compilateur n'a vu que la extern
déclaration, mais n'a pas encore exécuté la définition de variable réelle .
const map<int,int> m = create_map()
(et ainsi, initialiser les membres const d'une classe dans la liste d'initialisation:struct MyClass {const map<int, int> m; MyClass(); }; MyClass::MyClass() : m(create_map())
Ce n'est pas un problème 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 (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 il sera utilisé en premier, mais vous voulez vous assurer que les valeurs y sont disponibles.
Si disons, vous devez insérer des éléments dans une carte std :: map existante ... 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 CI-DESSOUS C'EST OBSOLÈTE #################
EDIT : La map_add_values
classe ci-dessous, qui était la solution originale que j'avais suggérée, échouerait en ce qui concerne GCC 4.5+. Veuillez consulter 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; // Plus tard quelque part le long du 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 OBSOLETE #####################
operator[]
ne prend qu'un seul argument.
error: conflicting declaration ‘map_add_values<int, int> my_map’
error: ‘my_map’ has a previous declaration as ‘std::map<int, int> my_map’
Voici une autre façon d'utiliser 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 ou 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} };
Par exemple:
const std::map<LogLevel, const char*> g_log_levels_dsc =
{
{ LogLevel::Disabled, "[---]" },
{ LogLevel::Info, "[inf]" },
{ LogLevel::Warning, "[wrn]" },
{ LogLevel::Error, "[err]" },
{ LogLevel::Debug, "[dbg]" }
};
Si map est un membre de données d'une classe, vous pouvez l'initialiser directement dans l'en-tête de la manière suivante (depuis C ++ 17):
// Example
template<>
class StringConverter<CacheMode> final
{
public:
static auto convert(CacheMode mode) -> const std::string&
{
// validate...
return s_modes.at(mode);
}
private:
static inline const std::map<CacheMode, std::string> s_modes =
{
{ CacheMode::All, "All" },
{ CacheMode::Selective, "Selective" },
{ CacheMode::None, "None" }
// etc
};
};
J'envelopperais la carte dans un objet statique et mettrais 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.
Je voulais juste partager un pur travail C ++ 98:
#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)
};
{1, 2}
place de std::pair<int, int>(1, 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 souhaitez pas utiliser boost, voici la solution que j'utilise lorsque j'ai besoin d'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 ] ) ] );
Vous avez de très bonnes réponses ici, mais je suis pour moi, cela ressemble à un cas de "quand tout ce que vous savez c'est un marteau" ...
La réponse la plus simple à la raison pour laquelle il n'y a pas de moyen standard d'initialiser une carte statique, c'est qu'il n'y a aucune bonne raison d'utiliser une carte statique ...
Une carte est une structure conçue pour une recherche rapide, d'un ensemble inconnu d'éléments. Si vous connaissez les éléments à l'avance, utilisez simplement un tableau C. Entrez les valeurs de manière triée ou exécutez le tri sur celles-ci si vous ne pouvez pas le faire. Vous pouvez ensuite obtenir les performances de log (n) en utilisant les fonctions stl :: pour boucler les entrées, lower_bound / upper_bound. Lorsque j'ai testé cela auparavant, ils fonctionnent normalement au moins 4 fois plus vite qu'une carte.
Les avantages sont multiples ... - des performances plus rapides (* 4, j'ai mesuré sur de nombreux types de CPU, c'est toujours autour de 4) - un débogage plus simple. Il est simplement plus facile de voir ce qui se passe avec une disposition linéaire. - Implémentations triviales d'opérations de copie, si cela devenait nécessaire. - Il n'alloue aucune mémoire au moment de l'exécution, donc ne lèvera jamais d'exception. - Il s'agit d'une interface standard et est donc très facile à partager entre les DLL, les langues, etc.
Je pourrais continuer, mais si vous en voulez plus, pourquoi ne pas consulter les nombreux blogs de Stroustrup sur le sujet.
map
est également une forme utile pour représenter une fonction partielle (fonction au sens mathématique; mais aussi, en quelque sorte, au sens de la programmation). Un tableau ne fait pas cela. Vous ne pouvez pas, par exemple, rechercher des données à partir d'un tableau à l'aide d'une chaîne.