Jak zainicjować prywatną statyczną mapę const w C++?

Potrzebuję tylko tablicy słownikowej lub asocjacyjnej string => int.

W tym przypadku istnieje Typ map C++.

Ale potrzebuję tylko jednej mapy dla wszystkich instancji(-> static) i tej mapy nie da się zmienić (- >const);

Znalazłem ten sposób z biblioteką boost

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

Czy jest inne rozwiązanie bez tej lib? Próbowałem czegoś takiego, ale zawsze są pewne problemy z inicjalizacją mapy.

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

};
Author: Meloun, 2010-04-14

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() {
}
 93
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-14 09:51:28

Standard C++11 wprowadził jednolitą inicjalizację, co znacznie upraszcza, jeśli twój kompilator ją obsługuje:

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


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

Zobacz także Ten rozdział z Professional C++, na unordered_maps.

 83
Author: David C. Bishop,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-01 21:43:10

Jeśli uważasz, że boost::assign::map_list_of jest przydatna, ale z jakiegoś powodu nie możesz jej użyć, możesz napisać własne :

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';
}

Warto wiedzieć, jak takie rzeczy działają, zwłaszcza gdy są tak krótkie, ale w tym przypadku użyłbym funkcji:

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
Author: Yu Hao,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-14 14:53:42

Udało mi się! :)

Działa dobrze bez 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
Author: user2622030,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-14 14:55:44

Jeśli mapa ma zawierać tylko wpisy, które są znane w czasie kompilacji, a klucze do mapy są liczbami całkowitymi, to nie musisz w ogóle używać mapy.

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
Author: Matthew T. Staebler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-14 10:33:31

Inne podejście do problemu:

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
}

Jest to bardziej efektywne, ponieważ nie ma kopii jednego typu ze stosu na stertę (włączając konstruktor, destruktory na wszystkich elementach). To, czy ma to znaczenie, zależy od przypadku użycia. To nie ma znaczenia ze sznurkami! (ale możesz lub nie możesz znaleźć tej wersji "cleaner")

 4
Author: ypnos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-14 10:32:12

Jeśli używasz kompilatora, który nadal nie obsługuje universal initialization lub masz zastrzeżenia do używania Boost, inną możliwą alternatywą będzie następująca

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
Author: Abhijit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-21 08:23:30

Możesz spróbować tego:

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

Z tą implementacją Twoje klasy constant static map są członkiem prywatnym i mogą być dostępne dla innych klas przy użyciu publicznej metody get. Inaczej ponieważ jest stała i nie może się zmienić, możesz usunąć metodę public get i przenieść zmienną map do sekcji klasy publiczne. Zostawiłbym jednak metodę createMap prywatną lub chronioną, jeśli wymagane jest dziedziczenie i lub polimorfizm. Oto kilka próbek użytkowania.

 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's reset method on
 // this class object. 

 // This will only work on static methods only, and all data in static methods must be available first.

Edytowałem swój oryginalny post, nie było nic złego w oryginalnym kodzie, w którym go napisałem skompilowany, zbudowany i uruchomiony poprawnie, po prostu moja pierwsza wersja przedstawiłem jako odpowiedź mapa została zadeklarowana jako publiczna i mapa była const, ale nie była statyczna.

 1
Author: Francis Cugler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-18 03:17:52

Wywołanie funkcji nie może pojawić się w wyrażeniu ciągłym.

Spróbuj tego: (tylko przykład)

#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
Author: Prasoon Saurav,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-14 09:56:02

Często używam tego wzoru i polecam ci go również używać:

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;

Jasne, że nie jest zbyt czytelny, ale bez innych libów najlepiej to zrobić. Również nie będzie żadnych zbędnych operacji, takich jak kopiowanie z jednej mapy do drugiej, jak w Twojej próbie.

Jest to jeszcze bardziej przydatne wewnątrz funkcji: Zamiast:

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

Użyj następującego:

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

Nie dość, że nie potrzebujesz już tutaj do obsługi zmiennej boolean, to nie będziesz miał ukrytej zmiennej globalnej jest to sprawdzane, jeśli inicjalizacja zmiennej statycznej wewnątrz funkcji została już wywołana.

 -2
Author: Pavel Chikulaev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-14 11:02:57