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

huangapple go评论90阅读模式
英文:

std::unordered_map using a template class pointer as a key

问题

我是cpp的初学者,我有一些类似这样的代码:

```cpp
#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");

<details>
<summary>英文:</summary>

**I&#39;m a beginner for cpp,and I have some codes like this:**
```cpp
#include &lt;iostream&gt;
#include &lt;utility&gt;
#include &lt;map&gt;
#include &lt;unordered_map&gt;


template&lt;typename T,typename EX&gt;
class Attachable
{
	
	static std::unordered_map&lt;T*,Attachable&lt;T,EX&gt;&gt; attachCaches;

	std::unordered_map&lt;std::string,EX&gt; datas;

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

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

	static Attachable&lt;T,EX&gt; attach(T* sender)
	{
		if(attachCaches.find(sender)==attachCaches.end())
		{
			attachCaches.insert(std::make_pair((sender),Attachable&lt;T,EX&gt;(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&lt;Tester,std::string&gt;::attach(a).set(&quot;test&quot;,&quot;typeOfInt&quot;);

	std::cout&lt;&lt; Attachable&lt;Tester,std::string&gt;::attach(a).get(&quot;test&quot;);

}

When I try to compile this code , I will receive an error at <xhash>,line 952,at the function called

emplace(*_First);

    template &lt;class _Iter, class _Sent&gt;
    void _Insert_range_unchecked(_Iter _First, const _Sent _Last) {
        for (; _First != _Last; ++_First) {
            emplace(*_First);
        }
    }

I am trying to using some basic pointer like int,but this still not worked:

    int* a =new int(4);

	Attachable&lt;int,std::string&gt;::attach(a).set(&quot;test&quot;,&quot;typeOfInt&quot;);

	std::cout&lt;&lt; Attachable&lt;int,std::string&gt;::attach(a).get(&quot;test&quot;);

答案1

得分: 3

attachCaches[(sender)] 可能需要默认构造一个 Attachable 对象,如果发现 sender 不在映射中。但是 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。您的原始代码返回映射元素的临时副本;然后在该副本上调用 set;然后销毁了该副本。映射中的原始值从未更新,因此随后的 get 没有找到传递给 set 的值。

演示

英文:

attachCaches[(sender)] may need to default-construct an Attachabe object, if it turns out that sender is not in the map. But Attachable doesn't provide a default constructor. Since you actually know the key is always in the map, you can implement attach this way (also more efficient, as it eliminates redundant lookups):

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

    return it-&gt;second;
}

Note also how the function now returns Attachable by reference. Your original code returned a temporary copy of the map element; then called set on that copy; then that copy was destroyed. The original in the map was never updated, so a subsequent get didn't find the value passed to set.

Demo

huangapple
  • 本文由 发表于 2023年6月26日 10:14:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/76553176.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定