“没有模板参数的类std :: map”错误

时间:2009-07-22 05:42:12

标签: c++ gcc stl

我不得不说我不是使用STL的专家。这是我的问题,我有一个名为LdapClientManager的类,它维护了许多由ID管理的LDAP客户端。持有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;
}

不幸的是我在编译时遇到以下错误,这是什么意思。我还没有在谷歌找到解决方案。

LdapClientManager.cc:在没有模板参数的情况下使用的成员函数LdapClient* LdapClientManager::getLdapClient(unsigned int)': LdapClientManager.cc:33:模板类std :: map'

4 个答案:

答案 0 :(得分:11)

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

答案 1 :(得分:3)

这正是它所说的意思。 std::map类模板。它本身并不是一个阶级。它需要模板参数,就像您在定义LdapClientMap类型时使用的那样。稍后,你说std::map::end,编译器也说需要参数。

但你可能意味着_ldapClientMap.end()。每张地图都有自己的结局; end不是静态函数,因此您需要在实例上调用它。 如果它是静态的,您需要提供模板参数,就像您定义类型时一样:std::map<int, LdapClient*>::end

答案 2 :(得分:1)

std :: map :: end()是容器实例的成员函数,而不是通用值,因此您需要针对_ldapClientMap.end检查std :: map :: find()的结果( )。

另一些​​改进代码的建议:

  • 标准C ++容器具有值语义(它们希望存储实际对象而不是指向对象的指针)。如果你真的需要存储指向LdapClients而不是LdapClient对象本身的指针,我强烈建议将它们包装在适当的智能指针中,例如boost :: shared_ptr( not std :: auto_ptr,这将不起作用)。这样,std :: map的自动内存管理仍然可以工作并按预期破坏对象。如果您不想使用智能指针或将实际的LdapClient对象放入容器中,则必须手动管理对象的生命周期并在适当时调用delete以防止内存泄漏。我的偏好是将地图的类型更改为std :: map,除非LdapClient对象是多态的。
  • 除非您使用的是非常过时的编译器,否则检查常规new()的结果为0或NULL将不会产生任何新的见解,因为当它无法分配内存时,新抛出std :: bad_alloc无论什么原因。
  • 而不是使用_ldapClientMap [x] = y;要插入一个新元素,我会使用_ldapClientMap.insert(LdapClientMap :: value_type(x,y)),因为后者不会覆盖密钥x的现有值(前者会这样做)并且将返回'false'以防万一密钥已经存在于地图中。那当然是你的意图。

答案 3 :(得分:-1)

LdapClientMap _ldapClientMap;

您应该避免使用带有前导下划线的名称。从技术上讲,它是未定义的行为,即使编译器允许它,因为使用它会与当前或未来的保留名称冲突。