Ошибка "class std :: map используется без параметров шаблона" - PullRequest
2 голосов
/ 22 июля 2009

Я должен сказать, что я не эксперт по использованию STL. Вот моя проблема, у меня есть класс Called LdapClientManager, который поддерживает несколько клиентов LDAP, которые управляются ID. Контейнер, содержащий LdapClients, объявляется как переменная-член, т.е.

typedef std::map<int, LdapClient *> LdapClientMap;
LdapClientMap _ldapClientMap;

Следующая функция не компилируется с ошибкой:

LdapClient * LdapClientManager::getLdapClient(unsigned int templateID)
{
    // Do we have an LdapClient
    LdapClientMap::const_iterator it = _ldapClientMap.find(templateID);
    if (it == std::map::end) {
        // no existing client, lets create it
        LdapClient * ldapClient = new LdapClient();
        if (ldapClient == NULL) {
            // TODO: handle out of memory condition
        }

        _ldapClientMap[templateID] = ldapClient;
        return ldapClient;
    }

    return it->second;
}

К сожалению, я получаю следующую ошибку во время компиляции, что это значит. Я еще не нашел решение в Google.

LdapClientManager.cc: в функции-члене LdapClient* LdapClientManager::getLdapClient(unsigned int)': LdapClientManager.cc:33: шаблон класса std :: map ', используемый без параметров шаблона

Ответы [ 4 ]

11 голосов
/ 22 июля 2009

Заменить std::map::end на _ldapClientMap.end(). Кроме того, new никогда не возвращает 0, оно выдает исключение в случае неудачного выделения.

Обратите внимание, что программу можно сделать намного короче.

LdapClient * LdapClientManager::getLdapClient(unsigned int templateID)
{
    LdapClient *& value = _ldapClientMap[templateID];
    if (value == 0)
        value = new LdapClient();
    return value;
}
3 голосов
/ 22 июля 2009

Это означает именно то, что говорит, что означает. std::map - это шаблон класса . Это не класс сам по себе. Ему нужны параметры шаблона, как вы использовали, когда определяли тип LdapClientMap. Позже вы говорите std::map::end, а компилятор говорит, что тоже нужны параметры.

Но вы, вероятно, имели в виду _ldapClientMap.end(). У каждой карты есть свой конец; end не является статической функцией, поэтому вам нужно вызывать ее для экземпляра. Если бы это было статично, вам нужно было бы предоставить параметры шаблона, точно так же, как когда вы определили тип: std::map<int, LdapClient*>::end.

1 голос
/ 22 июля 2009

std :: map :: end () является функцией-членом экземпляра контейнера, а не универсальным значением, поэтому вам необходимо проверить результат std :: map :: find () по отношению к _ldapClientMap.end ( ).

Еще пара предложений по улучшению кода:

  • Стандартные контейнеры C ++ имеют семантику значений (они хотят хранить фактический объект, а не указатель на объект). Если вам действительно нужно хранить указатели на LdapClients вместо самих объектов LdapClient, я настоятельно рекомендую обернуть их в соответствующий умный указатель, такой как boost :: shared_ptr ( not std :: auto_ptr, который не будет работать) , Таким образом, автоматическое управление памятью std :: map по-прежнему будет работать и уничтожать объекты, как предполагалось. Если вы не хотите использовать умный указатель или помещать фактический объект LdapClient в контейнер, вам придется вручную управлять временем жизни объектов и вызывать delete в случае необходимости, чтобы предотвратить утечки памяти. Я предпочел бы изменить тип карты на std :: map, если только объекты LdapClient не являются полиморфными.
  • Если вы не используете очень устаревший компилятор, проверка результата регулярного new () со значением 0 или NULL не даст никаких новых идей, поскольку new бросает std :: bad_alloc в наши дни, когда он не может выделить память для по любой причине.
  • Вместо использования _ldapClientMap [x] = y; чтобы вставить новый элемент, я бы использовал _ldapClientMap.insert (LdapClientMap :: value_type (x, y)), так как последний не будет перезаписывать существующее значение для ключа x (что будет делать первый) и будет возвращать «false» в случае ключ уже существует на карте. Это, конечно, если это ваше намерение.
0 голосов
/ 22 июля 2009
LdapClientMap _ldapClientMap;

Вам следует избегать использования имен с начальным подчеркиванием. Технически это неопределенное поведение, даже если компилятор позволяет это, потому что, используя его, вы конфликтуете с текущими или будущими зарезервированными именами.

...