std :: map назначение места только для чтения - PullRequest
2 голосов
/ 26 июня 2010

У меня есть static std::map<std::string, CreateGUIFunc> в классе, который в основном содержит строки, идентифицирующие типы GUI, а CreateGUIFunc является ссылкой на фабричную функцию.

В моем конструкторе у меня есть

if ( m_factoryRef.size() == 0 ) {
  m_factoryRef["image"] = &CreateGUI<Image>;
  m_factoryRef["button"] = &CreateGUI<Button>;
}
...

Однако, это дает мне ошибку, говорящую assignment of read-only location ‘GUIManager::m_factoryRef.std::map<_Key, _Tp, _Compare, _Alloc>::operator[] [with _Key = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _Tp = GUI*(), _Compare = std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, _Alloc = std::allocator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, GUI*()> >](((const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)(& std::basic_string<char, std::char_traits<char>, std::allocator<char> >(((const char*)"image"), ((const std::allocator<char>&)((const std::allocator<char>*)(& std::allocator<char>())))))))’|

Я не уверен, почему это назначение только для чтения. Я также попытался изменить его на обычный член, просто чтобы посмотреть, может ли это быть связано со статичностью, но то же самое.

В чем проблема?

Редактировать: Некоторые определения, чтобы сделать вещи немного яснее

// these are all private

typedef GUI* CreateGUIFunc();

template<class T>
GUI* GUIManager::CreateGUI( std::string &filepath, int x, int y ) {
  return new T( filepath, x, y );
}

static std::map<std::string, CreateGUIFunc> m_factoryRef;

P.S. Если есть более понятный способ инициализации статической карты, пожалуйста, дайте мне знать.

Ответы [ 2 ]

1 голос
/ 26 июня 2010

Вот некоторые альтернативные инициализации для текущего C ++. Я не уверен, что вы подразумеваете под «статической» инициализацией, когда вы сказали, что ваш код находится в конструкторе. У меня есть догадки, но это не имеет значения. Выберите то, что вам кажется «чище».

if (m.empty()){
   m.insert (map<K,V>::value_type (k1, v1));
   m.insert (map<K.V>::value_type (k1, v1));
}

или

map<K,V>&  getmap() {
    static map<K,V>* m = 0;
    if (!m){
         m = new map<K,V>(); // never deleted.
        // insert.
    }
    return *m;
}

или

namespace /*anon*/ {
      map<K,V>* init_map () { 
         map<K,V>* m = new map<K,V>();
         // insertions here.
         return m; // return by val. can move in c++0x.
      }
}

map<K,V> Foo::m = *init_map ();

или

namespace /*anon*/ {
          map<K,V>* init_map () { 
             map<K,V>* m = new map<K,V>();
             // insertions here.
             return m; // return by val. can move in c++0x.
          }
}

map<K,V>&  Foo::get_map () { /* static singleton accessor */
     static map<K,V> * m = init_map ();
     return *m;
}

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

0 голосов
/ 26 июня 2010

В C ++ typedef GUI* CreateGUIFunc(); - это не функция с неопределенными параметрами, а функция без параметров. Так что ни одна из ваших функций не соответствует этому типу. То, что вы хотите, это typedef GUI* (*CreateGUIFunc)( std::string &filepath, int x, int y );

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...