Inicializando un std :: map estático en C ++

¿Cuál es la forma correcta de inicializar un mapa estático? ¿Necesitamos una función estática que lo inicialice?

Usando C ++ 11:

#include  using namespace std; map m = {{1, 'a'}, {3, 'b'}, {5, 'c'}, {7, 'd'}}; 

Usando Boost.Assign :

 #include  #include "boost/assign.hpp" using namespace std; using namespace boost::assign; map m = map_list_of (1, 'a') (3, 'b') (5, 'c') (7, 'd'); 

La mejor manera es usar una función:

 #include  using namespace std; map create_map() { map m; m[1] = 2; m[3] = 4; m[5] = 6; return m; } map m = create_map(); 

No es un problema complicado hacer algo similar para impulsar. Aquí hay una clase con solo tres funciones, incluido el constructor, para replicar qué impulso hizo (casi).

 template  class create_map { private: std::map m_map; public: create_map(const T& key, const U& val) { m_map[key] = val; } create_map& operator()(const T& key, const U& val) { m_map[key] = val; return *this; } operator std::map() { return m_map; } }; 

Uso:

 std :: map mymap = create_map  (1,2) (3,4) (5,6);

El código anterior funciona mejor para la inicialización de variables globales o miembros estáticos de una clase que debe inicializarse y no tiene idea de cuándo se usa primero, pero desea asegurarse de que los valores estén disponibles en ella.

Si, por ejemplo, tienes que insertar elementos en un std :: map existente … aquí hay otra clase para ti.

 template  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()); } }; 

Uso:

 typedef std::map Int2IntMap; Int2IntMap testMap; map_add_values(1,2)(3,4)(5,6).to(testMap); 

Véalo en acción con GCC 4.7.2 aquí: http://ideone.com/3uYJiH

############### TODO LO SIGUIENTE ES OBSOLETO #################

EDITAR : La clase map_add_values continuación, que era la solución original que había sugerido, fallaría cuando se trata de GCC 4.5+. Mire el código anterior para saber cómo agregar valores al mapa existente.

 template class map_add_values { private: std::map& m_map; public: map_add_values(std::map& _map):m_map(_map){} map_add_values& operator()(const T& _key, const U& _val) { m_map[key] = val; return *this; } }; 

Uso:

  std :: map  my_map;
 // Más tarde en algún lugar a lo largo del código
 map_add_values ​​ (my_map) (1,2) (3,4) (5,6); 

NOTA: Anteriormente utilicé un operator [] para agregar los valores reales. Esto no es posible según lo comentado por dalle.

##################### FIN DE LA SECCIÓN OBSOLETA #####################

Aquí hay otra manera que usa el constructor de datos de 2 elementos. No se necesitan funciones para inicializarlo. No hay código de terceros (Boost), no hay funciones estáticas u objetos, no hay trucos, simplemente C ++:

 #include  #include  typedef std::map 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); 

Desde que escribí esta respuesta C ++ 11 está fuera. Ahora puede inicializar directamente los contenedores STL utilizando la nueva función de lista de inicializadores:

 const MyMap myMap = { {"hello", 42}, {"world", 88} }; 

Me gustaría envolver el mapa dentro de un objeto estático, y poner el código de inicialización del mapa en el constructor de este objeto, de esta manera usted está seguro de que el mapa se crea antes de que se ejecute el código de inicialización.

Solo quería compartir un C ++ 98 puro:

 #include  std::map aka; struct akaInit { akaInit() { aka[ "George" ] = "John"; aka[ "Joe" ] = "Al"; aka[ "Phil" ] = "Sue"; aka[ "Smitty" ] = "Yando"; } } AkaInit; 

Puedes probar:

 std::map  mymap = { std::pair  (1, 1), std::pair  (2, 2), std::pair  (2, 2) }; 

Esto es similar a PierreBdR , sin copiar el mapa.

 #include  using namespace std; bool create_map(map &m) { m[1] = 2; m[3] = 4; m[5] = 6; return true; } static map m; static bool _dummy = create_map (m); 

Por ejemplo:

 const std::map g_logLevelsDescriptions = { { LoggerLevel::llNothing, "Logging disabled" }, { LoggerLevel::llInfo, "Base information" }, { LoggerLevel::llWarn, "Warnings" }, { LoggerLevel::llError, "Errors" }, { LoggerLevel::llDebug, "All information: debug-mode" } }; 

Si está atascado con C ++ 98 y no quiere usar boost, aquí está la solución que uso cuando necesito inicializar un mapa estático:

 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 ] ) ] ); 

Tienes algunas muy buenas respuestas aquí, pero estoy para mí, parece un caso de “cuando todo lo que sabes es un martillo” …

La respuesta más simple a por qué no hay una forma estándar de inicializar un mapa estático, es que no hay una buena razón para usar un mapa estático …

Un mapa es una estructura diseñada para una búsqueda rápida, de un conjunto desconocido de elementos. Si conoce los elementos de antemano, simplemente use un C-array. Ingrese los valores de una manera ordenada, o ejecute ordenar en ellos, si no puede hacer esto. A continuación, puede obtener el rendimiento de log (n) mediante el uso de las funciones stl :: para realizar entradas en bucle, lower_bound / upper_bound. Cuando lo he probado previamente, normalmente funcionan al menos 4 veces más rápido que un mapa.

Las ventajas son muchas: … un rendimiento más rápido (* 4, he medido en muchos tipos de CPU, siempre es alrededor de 4) – depuración más simple. Es más fácil ver qué está pasando con un diseño lineal. – Implementaciones triviales de operaciones de copia, en caso de que sea necesario. – No asigna memoria en tiempo de ejecución, por lo que nunca lanzará una excepción. – Es una interfaz estándar, por lo que es muy fácil de compartir, DLL o idiomas, etc.

Podría seguir, pero si quiere más, ¿por qué no mira los numerosos blogs de Stroustrup sobre el tema?