Не удается получить доступ к элементу карты из указателя - PullRequest
2 голосов
/ 26 марта 2010

Это мой первый вопрос:)

Я храню конфигурацию моей программы в форме Group->Key->Value, как старые INI. Я храню информацию в паре структур.

Во-первых, я использую std::map со строкой + ptr для информации о группах (имя группы в ключе строки). Второе значение std::map является указателем на вторую структуру, a std::list из std::map с, с финишными парами Key->Value.

Структура пар «ключ-> значение» создается динамически, поэтому структура конфигурации:

std::map< std::string , std::list< std::map<std::string,std::string> >* > lv1;

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

bool isConfigLv1(std::string);
bool ConfigManager::isConfigLv1(std::string s) {
    return !(lv1.find(s)==lv1.end());
}

Второй способ сводит меня с ума ... Он проверяет наличие ключа внутри группы.

bool isConfigLv2(std::string,std::string);
bool ConfigManager::isConfigLv2(std::string s,std::string d) {
    if(!isConfigLv1(s))
        return false;
    std::map< std::string , std::list< std::map<std::string,std::string> >* >::iterator it;
    std::list< std::map<std::string,std::string> >* keyValue;
    std::list< std::map<std::string,std::string> >::iterator keyValueIt;
    it = lv1.find(s);
    keyValue = (*it).second;
    for ( keyValueIt = keyValue->begin() ; keyValueIt != keyValue->end() ; keyValueIt++ )
        if(!((*keyValueIt).second.find(d)==(*keyValueIt).second.end()))
            return true;
    return false;
}

Я не понимаю, что не так. Компилятор говорит:

ConfigManager.cpp||In member function ‘bool ConfigManager::isConfigLv2(std::string, std::string)’:|
ConfigManager.cpp|(line over return true)|error: ‘class std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >’ has no member named ‘second’|

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

Есть предложения о том, что происходит?

Извините за мой английский: P, и подумайте, что я делаю это как упражнение, я знаю, что есть много классных менеджеров конфигурации.

Ответы [ 3 ]

2 голосов
/ 26 марта 2010

keyValueЭто не итератор карты, это итератор списка. Вы можете просто сделать

if (keyValueIt->find(d) != keyValueIt->end())
1 голос
/ 26 марта 2010

Я думаю, что Джоэл прав с

if (keyValueIt->find(d) != keyValueIt->end())

Однако я хотел бы призвать вас использовать некоторые определения типов, чтобы попытаться упростить ваш код. Использование typedefs может помочь при диагностике подобных проблем (и если вам повезет, ваш компилятор в результате даст вам более значимые сообщения об ошибках.

Например:

typedef std::map<std::string,std::string> KeyValueMap;
typedef std::list< KeyValueMap > ConfigurationList;
typedef std::map< std::string, ConfigurationList* > ConfigurationMap;

bool isConfigLv2(std::string,std::string);
bool ConfigManager::isConfigLv2(std::string s,std::string d) {
    if(!isConfigLv1(s))
        return false;

    ConfigurationMap::iterator it;
    ConfigurationList* keyValue;
    ConfigurationList::iterator keyValueIt;  // <- it's not a keyValue iterator, it's a ConfigList iterator!
    it = lv1.find(s);
    keyValue = (*it).second;
    for ( keyValueIt = keyValue->begin() ; keyValueIt != keyValue->end() ; keyValueIt++ )
        if(!((*keyValueIt).second.find(d)==(*keyValueIt).second.end()))
            return true;
    return false;
}

Упрощение типов делает для меня более очевидным, что keyValueI, вероятно, ошибочно (т.е. это фактически итератор списка, а не итератор KeyValueMap, и поэтому доступ '.second' является ошибочным.)

1 голос
/ 26 марта 2010

Если вам просто нужна структура group/key/value, вы слишком усложняете ее, у вас есть еще один уровень в структуре данных, тогда необходимый. Дополнительные list не нужны, достаточно map из maps:

// typedefs for readability:
typedef std::map<std::string, std::string> Entries;
typedef std::map<std::string, Entries> Groups;
// class member:
Groups m_groups;

bool ConfigManager::hasKey(const std::string& group, const std::string& key) 
{        
    Groups::const_iterator it = m_groups.find(group);
    if(it == m_groups.end())
        return false;

    const Entries& entries = it->second;
    return (entries.find(key) != entries.end());
}
...