Как инициализировать частную статическую карту константы в C++?

Мне нужны просто словарь или ассоциативный массив string => int.

Существует карта типа C++ для этого случая.

Но мне нужна только одна карта forall экземпляры (-> статичный), и эта карта не может быть изменена (-> константа);

Я нашел этот путь с библиотекой повышения

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

Есть ли другое решение без этого lib? Я попробовал что-то вроде этого, но всегда существуют некоторые проблемы с инициализацией карты.

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

};
96
задан Meloun 2 April 2014 в 21:33
поделиться

6 ответов

#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() {
}
102
ответ дан 24 November 2019 в 05:34
поделиться

Я часто использую этот шаблон и рекомендую вам также использовать его:

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;

Конечно, он не очень удобочитаем, но без других библиотек лучше всего можно. Также не будет никаких повторяющихся операций, таких как копирование с одной карты на другую, как в вашей попытке.

Это даже более полезно внутри функций: Вместо:

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

Используйте следующее:

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

Здесь вам не только больше не нужно иметь дело с логической переменной, но и у вас не будет скрытая глобальная переменная, которая проверяется, если инициализатор статической переменной внутри функции уже был вызван.

-2
ответ дан 24 November 2019 в 05:34
поделиться

Если вы считаете boost :: assign :: map_list_of полезным, но по какой-то причине не можете его использовать, вы можете написать свой собственный :

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

Полезно знать как такие вещи работают, особенно когда они такие короткие, но в этом случае я бы использовал функцию:

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
ответ дан 24 November 2019 в 05:34
поделиться

Вызов функции не может появляться в константном выражении.

попробуйте следующее: (просто пример)

#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
ответ дан 24 November 2019 в 05:34
поделиться

Другой подход к проблеме:

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
}

Это более эффективно, так как нет однотипного копирования из стека в кучу (включая конструктор, деструкторы на всех элементах). Важно это или нет, зависит от вашего случая использования. Для строк это не имеет значения! (но вы можете найти или не найти эту версию "более чистой")

6
ответ дан 24 November 2019 в 05:34
поделиться

Если карта должна содержать только записи, которые известны на момент компиляции, и ключи карты - целые числа, то вам вообще не нужно использовать карту.

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
    }
}
6
ответ дан 24 November 2019 в 05:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: