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

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

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

问题

  1. 我是cpp的初学者,我有一些类似这样的代码:
  2. ```cpp
  3. #include <iostream>
  4. #include <utility>
  5. #include <map>
  6. #include <unordered_map>
  7. template<typename T,typename EX>
  8. class Attachable
  9. {
  10. static std::unordered_map<T*,Attachable<T,EX>> attachCaches;
  11. std::unordered_map<std::string,EX> datas;
  12. Attachable(T* sender):m_attachedObj(sender)
  13. {
  14. }
  15. bool operator==(const Attachable& other)const
  16. {
  17. return m_attachedObj == other.m_attachedObj;
  18. }
  19. public:
  20. static Attachable<T,EX> attach(T* sender)
  21. {
  22. if(attachCaches.find(sender)==attachCaches.end())
  23. {
  24. attachCaches.insert(std::make_pair(sender,Attachable<T,EX>(sender)));
  25. }
  26. return attachCaches[sender];
  27. }
  28. void set(std::string key,EX properties)
  29. {
  30. datas.insert(key,properties);
  31. }
  32. EX get(std::string key)
  33. {
  34. return datas.at(key);
  35. }
  36. private:
  37. T* m_attachedObj;
  38. };
  39. class Tester
  40. {
  41. public :
  42. Tester(){}
  43. };
  44. int main()
  45. {
  46. Tester* a =new Tester();
  47. Attachable<Tester,std::string>::attach(a).set("test","typeOfInt");
  48. std::cout<< Attachable<Tester,std::string>::attach(a).get("test");
  49. }

当我尝试编译这段代码时,我会在的第952行收到一个错误,出现在名为emplace(*_First);的函数处:

  1. template <class _Iter, class _Sent>
  2. void _Insert_range_unchecked(_Iter _First, const _Sent _Last) {
  3. for (; _First != _Last; ++_First) {
  4. emplace(*_First);
  5. }
  6. }

我尝试使用一些基本的指针,比如int,但仍然不起作用:

  1. int* a = new int(4);
  2. Attachable<int,std::string>::attach(a).set("test","typeOfInt");
  3. std::cout<< Attachable<int,std::string>::attach(a).get("test");
  1. <details>
  2. <summary>英文:</summary>
  3. **I&#39;m a beginner for cpp,and I have some codes like this:**
  4. ```cpp
  5. #include &lt;iostream&gt;
  6. #include &lt;utility&gt;
  7. #include &lt;map&gt;
  8. #include &lt;unordered_map&gt;
  9. template&lt;typename T,typename EX&gt;
  10. class Attachable
  11. {
  12. static std::unordered_map&lt;T*,Attachable&lt;T,EX&gt;&gt; attachCaches;
  13. std::unordered_map&lt;std::string,EX&gt; datas;
  14. Attachable(T* sender):m_attachedObj(sender)
  15. {
  16. }
  17. bool operator==(const Attachable&amp; other)const
  18. {
  19. return m_attachedObj == other.m_attachedObj;
  20. }
  21. public:
  22. static Attachable&lt;T,EX&gt; attach(T* sender)
  23. {
  24. if(attachCaches.find(sender)==attachCaches.end())
  25. {
  26. attachCaches.insert(std::make_pair((sender),Attachable&lt;T,EX&gt;(sender)));
  27. }
  28. return attachCaches[(sender)];
  29. }
  30. void set(std::string key,EX properties)
  31. {
  32. datas.insert(key,properties);
  33. }
  34. EX get(std::string key)
  35. {
  36. return datas.at(key);
  37. }
  38. private:
  39. T* m_attachedObj;
  40. };
  41. class Tester
  42. {
  43. public :
  44. Tester(){}
  45. };
  46. int main()
  47. {
  48. Tester* a =new Tester();
  49. Attachable&lt;Tester,std::string&gt;::attach(a).set(&quot;test&quot;,&quot;typeOfInt&quot;);
  50. std::cout&lt;&lt; Attachable&lt;Tester,std::string&gt;::attach(a).get(&quot;test&quot;);
  51. }

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

emplace(*_First);

  1. template &lt;class _Iter, class _Sent&gt;
  2. void _Insert_range_unchecked(_Iter _First, const _Sent _Last) {
  3. for (; _First != _Last; ++_First) {
  4. emplace(*_First);
  5. }
  6. }

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

  1. int* a =new int(4);
  2. Attachable&lt;int,std::string&gt;::attach(a).set(&quot;test&quot;,&quot;typeOfInt&quot;);
  3. std::cout&lt;&lt; Attachable&lt;int,std::string&gt;::attach(a).get(&quot;test&quot;);

答案1

得分: 3

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

  1. static Attachable<T, EX>& attach(T* sender)
  2. {
  3. auto it = attachCaches.find(sender);
  4. if (it == attachCaches.end())
  5. {
  6. it = attachCaches.emplace(sender, Attachable<T, EX>(sender)).first;
  7. }
  8. return it->second;
  9. }

请注意,函数现在通过引用返回 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):

  1. static Attachable&lt;T,EX&gt;&amp; attach(T* sender)
  2. {
  3. auto it = attachCaches.find(sender);
  4. if (it == attachCaches.end())
  5. {
  6. it = attachCaches.emplace(sender, Attachable&lt;T,EX&gt;(sender)).first;
  7. }
  8. return it-&gt;second;
  9. }

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:

确定