How to initialize a private static map const in C ++?

I only need a dictionary or an associative array string => int .

In this case, there is a map type of C ++.

But I need only one map for all instances (-> static), and this map cannot be changed (-> const);

I found this way using boost library

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

Is there any other solution without this library? I tried something like this, but there are always some problems with initializing the card.

 class myClass{ private: static map<int,int> create_map() { map<int,int> m; m[1] = 2; m[3] = 4; m[5] = 6; return m; } static map<int,int> myMap = create_map(); }; 
+76
c ++ initialization static const map
Apr 14 '10 at 9:38 on
source share
10 answers
 #include <map> using namespace std; struct A{ static map<int,int> create_map() { map<int,int> m; m[1] = 2; m[3] = 4; m[5] = 6; return m; } static const map<int,int> myMap; }; const map<int,int> A:: myMap = A::create_map(); int main() { } 
+83
Apr 14 '10 at 9:44
source share

The C ++ 11 standard introduces unified initialization, which makes it much easier if your compiler supports it:

 //myClass.hpp class myClass { private: static map<int,int> myMap; }; 


 //myClass.cpp map<int,int> myClass::myMap = { {1, 2}, {3, 4}, {5, 6} }; 

See also this section from Professional C ++ on unordered_maps.

+77
Dec 31 '11 at 2:21 a.m.
source share

If you found boost::assign::map_list_of useful, but for some reason cannot use it, you can write your own :

 template<class K, class V> struct map_list_of_type { typedef std::map<K, V> Map; Map data; map_list_of_type(K k, V v) { data[k] = v; } map_list_of_type& operator()(K k, V v) { data[k] = v; return *this; } operator Map const&() const { return data; } }; template<class K, class V> map_list_of_type<K, V> my_map_list_of(K k, V v) { return map_list_of_type<K, V>(k, v); } int main() { std::map<int, char> example = my_map_list_of(1, 'a') (2, 'b') (3, 'c'); cout << example << '\n'; } 

It is useful to know how such things work, especially when they are so short, but in this case I would use a function:

a.hpp

 struct A { static map<int, int> const m; }; 

a.cpp

 namespace { map<int,int> create_map() { map<int, int> m; m[1] = 2; // etc. return m; } } map<int, int> const A::m = create_map(); 
+11
Apr 14 '10 at 10:21
source share

I did it! :)

Works great without C ++ 11

 class MyClass { typedef std::map<std::string, int> MyMap; struct T { const char* Name; int Num; operator MyMap::value_type() const { return std::pair<std::string, int>(Name, Num); } }; static const T MapPairs[]; static const MyMap TheMap; }; const MyClass::T MyClass::MapPairs[] = { { "Jan", 1 }, { "Feb", 2 }, { "Mar", 3 } }; const MyClass::MyMap MyClass::TheMap(MapPairs, MapPairs + 3); 
+11
Aug 14 '13 at 14:40
source share

If the card should contain only records that are known at compile time, and the keys to the card are integers, then you do not need to use the card at all.

 char get_value(int key) { switch (key) { case 1: return 'a'; case 2: return 'b'; case 3: return 'c'; default: // Do whatever is appropriate when the key is not valid } } 
+7
Apr 14 '10 at
source share

Another approach to the problem:

 struct A { static const map<int, string> * singleton_map() { static map<int, string>* m = NULL; if (!m) { m = new map<int, string>; m[42] = "42" // ... other initializations } return m; } // rest of the class } 

This is more efficient since there is no copy of the same type from the stack to the heap (including constructor, destructors for all elements). It doesn't matter if it depends on your use. It doesn't matter with the strings! (but you may or may not find this version of "cleaner")

+4
Apr 14 '10 at 10:32
source share

If you are using a compiler that still does not support universal initialization, or you have redundancy when using Boost, the following possible alternative would be the following:

 std::map<int, int> m = [] () { std::pair<int,int> _m[] = { std::make_pair(1 , sizeof(2)), std::make_pair(3 , sizeof(4)), std::make_pair(5 , sizeof(6))}; std::map<int, int> m; for (auto data: _m) { m[data.first] = data.second; } return m; }(); 
+2
Jul 21 '13 at 8:23
source share

You can try the following:

Myclass.h

 class MyClass { private: static const std::map<key, value> m_myMap; static const std::map<key, value> createMyStaticConstantMap(); public: static std::map<key, value> getMyConstantStaticMap( return m_myMap ); }; //MyClass 

Myclass.cpp

 #include "MyClass.h" const std::map<key, value> MyClass::m_myMap = MyClass::createMyStaticConstantMap(); const std::map<key, value> MyClass::createMyStaticConstantMap() { std::map<key, value> mMap; mMap.insert( std::make_pair( key1, value1 ) ); mMap.insert( std::make_pair( key2, value2 ) ); // .... mMap.insert( std::make_pair( lastKey, lastValue ) ); return mMap; } // createMyStaticConstantMap 

With this implementation, your persistent static class maps are private members and can be accessed by other classes using the public get method. Otherwise, since it is constant and cannot be changed, you can remove the public get method and move the map variable to the public section of the classes. However, I would leave the createMap method private or protected if inheritance and / or polymorphism is required. Here are some examples of use.

  std::map<key,value> m1 = MyClass::getMyMap(); // then do work on m1 or unsigned index = some predetermined value MyClass::getMyMap().at( index ); // As long as index is valid this will // retun map.second or map->second value so if in this case key is an // unsigned and value is a std::string then you could do std::cout << std::string( MyClass::getMyMap().at( some index that exists in map ) ); // and it will print out to the console the string locted in the map at this index. //You can do this before any class object is instantiated or declared. //If you are using a pointer to your class such as: std::shared_ptr<MyClass> || std::unique_ptr<MyClass> // Then it would look like this: pMyClass->getMyMap().at( index ); // And Will do the same as above // Even if you have not yet called the std pointer reset method on // this class object. // This will only work on static methods only, and all data in static methods must be available first. 

I edited my original post, there was nothing wrong with the source code in which I posted it, compiled, built and worked correctly, it was just my first version, which I submitted as an answer, was declared as public, and the map was const, but was not static.

+1
Mar 17 '15 at 15:38
source share

A function call cannot appear in constant expression.

try the following: (just an example)

 #include <map> #include <iostream> using std::map; using std::cout; class myClass{ public: static map<int,int> create_map() { map<int,int> m; m[1] = 2; m[3] = 4; m[5] = 6; return m; } const static map<int,int> myMap; }; const map<int,int>myClass::myMap = create_map(); int main(){ map<int,int> t=myClass::create_map(); std::cout<<t[1]; //prints 2 } 
0
Apr 14 '10 at 9:51 on
source share

I often use this template and recommend you use it:

 class MyMap : public std::map<int, int> { public: MyMap() { //either insert(make_pair(1, 2)); insert(make_pair(3, 4)); insert(make_pair(5, 6)); //or (*this)[1] = 2; (*this)[3] = 4; (*this)[5] = 6; } } const static my_map; 

Of course, this is not very readable, but without other libraries it is best to do it. There will also be no redundant operations, such as copying from one card to another, as in your attempt.

This is even more useful inside functions: Instead:

 void foo() { static bool initComplete = false; static Map map; if (!initComplete) { initComplete = true; map= ...; } } 

Use the following:

 void bar() { struct MyMap : Map { MyMap() { ... } } static mymap; } 

You no longer have to deal with a boolean variable, you will not have a hidden global variable that is checked if the static variable initializer inside the function has already been called.

-one
Apr 14 '10 at 10:41
source share



All Articles