std::unordered_map 使用模板类指针作为键

3
我是一个C++的初学者,我有一些类似这样的代码:
#include <iostream>
#include <utility>
#include <map>
#include <unordered_map>


template<typename T,typename EX>
class Attachable
{
    
    static std::unordered_map<T*,Attachable<T,EX>> attachCaches;

    std::unordered_map<std::string,EX> datas;

    Attachable(T* sender):m_attachedObj(sender)
    {
    }

    bool operator==(const Attachable& other)const
    {
        return m_attachedObj == other.m_attachedObj;
    }
public:

    static Attachable<T,EX> attach(T* sender)
    {
        if(attachCaches.find(sender)==attachCaches.end())
        {
            attachCaches.insert(std::make_pair((sender),Attachable<T,EX>(sender)));
        }

        return attachCaches[(sender)];
    }


    void set(std::string key,EX properties)
    {
        datas.insert(key,properties);
    }

    EX get(std::string key)
    {
        return datas.at(key);
    }

private:
    T* m_attachedObj;
};


class Tester
{
public :
    Tester(){}
};

int main()
{
    Tester* a =new Tester();

    Attachable<Tester,std::string>::attach(a).set("test","typeOfInt");

    std::cout<< Attachable<Tester,std::string>::attach(a).get("test");

}

当我尝试编译这段代码时,在第952行的函数emplace(*_First);处会收到一个错误。
    template <class _Iter, class _Sent>
    void _Insert_range_unchecked(_Iter _First, const _Sent _Last) {
        for (; _First != _Last; ++_First) {
            emplace(*_First);
        }
    }

我试图使用一些基本的指针,比如int,但这仍然没有起作用。
    int* a =new int(4);

    Attachable<int,std::string>::attach(a).set("test","typeOfInt");

    std::cout<< Attachable<int,std::string>::attach(a).get("test");

你真的需要指针吗?int* a = new int(4); 这段代码有点不太好。 - Jarod42
【OT】:“data”已经是复数形式了,“datas”是不正确的。 - Jarod42
- Jarod42
@Jarod42 谢谢你的回复!对不起我的英文很差,我也在学习中。关于我的代码,我想给堆中的每个对象添加一个扩展值(这就是为什么我需要一个指针作为哈希映射的键),这样我就可以使用 Attachable&lt;X,XX&gt;::attach(a).set(&quot;a key&quot;,XXXX); 来设置任意类型的值,所以 int* a =new int(4) 只是为了测试,我已经知道这个例子不好,无论如何,感谢你的指导! - xiangyue qiu
@Jarod42 谢谢你的回复!对不起我的英文很差,我也在学习中。关于我的代码,我想给堆中的每个对象一个扩展值(这就是为什么我需要一个指针作为哈希映射的键),这样我就可以使用Attachable<X,XX>::attach(a).set("a key",XXXX);来设置任何类型的值,所以int* a =new int(4)只是为了测试,我已经知道这个例子不好,无论如何,感谢你的指导! - xiangyue qiu
显示剩余2条评论
1个回答

3

attachCaches[(sender)]如果发现sender不在映射中,可能需要默认构造一个Attachabe对象。但是Attachable没有提供默认构造函数。由于您实际上知道键始终存在于映射中,可以通过以下方式实现attach(还更高效,因为它消除了冗余的查找):

static Attachable<T,EX>& attach(T* sender)
{
    auto it = attachCaches.find(sender);
    if (it == attachCaches.end())
    {
        it = attachCaches.emplace(sender, Attachable<T,EX>(sender)).first;
    }

    return it->second;
}

注意一下函数现在是通过引用返回Attachable。你原来的代码返回了一个临时副本的map元素,然后在副本上调用了set方法,然后这个副本被销毁了。原始的map中的值从未更新,所以后续的get方法找不到传递给set方法的值。 演示

你还可以简单地使用return attachCaches.emplace(sender, Attachable&lt;T,EX&gt;(sender)).first-&gt;second来避免额外的查找(这里可能有多余的构造函数,但是它们很廉价)。 - Jarod42
你尝试的时候会发生什么?有看到错误信息吗?它们说了什么?在我加上之前缺失的#include <string>后,似乎对我来说是可以工作的。 - Igor Tandetnik
我在Windows上使用Visual Studio,创建了一个空的C++项目,并创建了一个main.cpp文件,将这些代码粘贴进去并构建,然后遇到了错误代码LNK2001LNK1120,它们都被描述为“未解析的外部符号”。其他细节太长无法作为评论,所以我只粘贴了一个快捷方式:private: static class std::unordered_map<class A *,class Attachable<class A,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char>....$allocator@U?$pair@QEAVA@@V?$Attachable@VA@@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@@@std@@@4@@std@@A) - xiangyue qiu
你可能错过了我演示的这部分代码:template&lt;typename T,typename EX&gt; std::unordered_map&lt;T*,Attachable&lt;T,EX&gt;&gt; Attachable&lt;T,EX&gt;::attachCaches;(在类定义之外)。 - Igor Tandetnik
你可能漏掉了我演示的这部分内容:template<typename T,typename EX> std::unordered_map<T*,Attachable<T,EX>> Attachable<T,EX>::attachCaches;(在类定义之外)。 - Igor Tandetnik
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接