“类 std::map 在没有模板参数的情况下使用” 错误

发布于 2024-07-27 17:36:59 字数 1020 浏览 0 评论 0原文

我不得不说我不是使用 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;
}

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

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

I'd have to say I'm no expert on using the STL. Here's my problem, I have a class Called LdapClientManager which maintains a number of LDAP clients that are managed by ID. The container holding the LdapClients is declared as a member variable i.e.

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

The following function fails to compile with the error:

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

Unfortunately I get the following error at compile time, what does it mean. I haven't found a solution in google as yet.

LdapClientManager.cc: In member function LdapClient*
LdapClientManager::getLdapClient(unsigned int)':
LdapClientManager.cc:33:
template class std::map' used without template parameters

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

往日情怀 2024-08-03 17:36:59

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

Replace std::map::end with _ldapClientMap.end().
Also, new never returns 0, it throws an exception if the allocation fails.

Note that the program can be made much shorter.

LdapClient * LdapClientManager::getLdapClient(unsigned int templateID)
{
    LdapClient *& value = _ldapClientMap[templateID];
    if (value == 0)
        value = new LdapClient();
    return value;
}
心病无药医 2024-08-03 17:36:59

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

但您可能指的是 _ldapClientMap.end()。 每张地图都有自己的终点; end 不是静态函数,因此您需要在实例上调用它。 如果它是静态的,您将需要提供模板参数,就像定义类型时一样:std::map::end

It means exactly what it says it means. std::map is a class template. It is not a class in and of itself. It needs template parameters, like you used when you defined the LdapClientMap type. Later, you say std::map::end, and the compiler says that needs parameters, too.

But you probably meant _ldapClientMap.end(). Each map has its own end; end is not a static function, so you need to call it on an instance. If it were static, you would have needed to provide template parameters, just like when you defined the type: std::map<int, LdapClient*>::end.

指尖上的星空 2024-08-03 17:36:59

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

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

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

std::map::end() is a member function of the container instance and not a universal value, so you'll need to check the result of std::map::find() against _ldapClientMap.end().

Another couple of suggestions to improve the code:

  • Standard C++ containers have value semantics (they want to store the actual object and not a pointer to the object). If you really need to store pointers to LdapClients instead of the LdapClient objects themselves, I would strongly recommend wrapping them in an appropriate smart pointer like boost::shared_ptr (not std::auto_ptr, which will not work). This way, the automatic memory management of the std::map will still work and destroy the objects as intended. If you don't want to use a smart pointer or put the actual LdapClient object into the container, you will have to manually manage the objects' lifetime and call delete when appropriate to prevent memory leaks. My preference would be to change the type of the map to std::map unless the LdapClient objects are polymorphic.
  • Unless you are using a very out of date compiler, checking the result of regular new() against 0 or NULL will not yield any new insights as new throws a std::bad_alloc these days when it can't allocated memory for whatever reason.
  • Instead of using _ldapClientMap[x] = y; to insert a new element, I would use _ldapClientMap.insert(LdapClientMap::value_type(x,y)) as the latter will not overwrite an existing value for key x (which the former will do) and will return 'false' in case the key already exists in the map. That is of course if that is your intention.
怎会甘心 2024-08-03 17:36:59
LdapClientMap _ldapClientMap;

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

LdapClientMap _ldapClientMap;

You should avoid using names with a leading underscore. Technically it is undefined behavior, even if the compiler allows it because by using it you conflict with current or future reserved names.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文