fork download
  1. // http://stackoverflow.com/questions/37771121/stored-by-value-pool-that-support-polymorphism-how-to-use-smart-pointer
  2.  
  3. #include <unordered_map>
  4. #include <iostream>
  5.  
  6. template<class T> struct Handle;
  7.  
  8.  
  9. struct PoolBase
  10. {
  11. virtual void destroy(int index) = 0;
  12. virtual void* get(int index) = 0;
  13. virtual bool isAlive(int index) const = 0;
  14. };
  15.  
  16.  
  17. template<class T>
  18. struct Pool : public PoolBase
  19. {
  20. int nextIndex;
  21.  
  22. typedef std::unordered_map<int, T> Map;
  23. Map objects;
  24.  
  25.  
  26. Pool() : nextIndex(0) {}
  27.  
  28. Handle<T> create()
  29. {
  30. int index = nextIndex++;
  31. objects[index] = T();
  32. return Handle<T>(this, index);
  33. }
  34.  
  35. void destroy(int index) override
  36. {
  37. objects.erase(index);
  38. }
  39.  
  40. void* get(int index) override
  41. {
  42. typename Map::iterator it = objects.find(index);
  43. return it == objects.end() ? nullptr : &it->second;
  44. }
  45.  
  46. bool isAlive(int index) const override
  47. {
  48. typename Map::const_iterator it = objects.find(index);
  49. return it != objects.end();
  50. }
  51. };
  52.  
  53.  
  54. template<class T>
  55. struct Handle
  56. {
  57. PoolBase* pool_;
  58. int pool_index_;
  59.  
  60.  
  61. Handle() : pool_(nullptr), pool_index_(0) {}
  62. Handle(PoolBase* pool, int index) : pool_(pool), pool_index_(index) {}
  63.  
  64. // Conversion Constructor
  65. template<class D>
  66. Handle(const Handle<D>& orig)
  67. {
  68. T* Cannot_cast_Handle = (D*)nullptr;
  69. (void)Cannot_cast_Handle;
  70.  
  71. pool_ = orig.pool_;
  72. pool_index_ = orig.pool_index_;
  73. }
  74.  
  75. explicit operator bool() const
  76. {
  77. return pool_->isAlive(pool_index_);
  78. }
  79.  
  80. T* operator->()
  81. {
  82. return static_cast<T*>( pool_->get(pool_index_) );
  83. }
  84.  
  85. void destroy()
  86. {
  87. pool_->destroy(pool_index_);
  88. }
  89. };
  90.  
  91.  
  92. template<class D, class S>
  93. Handle<D> static_handle_cast(const Handle<S>& src)
  94. {
  95. return Handle<D>(src.pool_, src.pool_index_);
  96. }
  97.  
  98.  
  99. struct Base
  100. {
  101. virtual void print() { std::cout << "Base::print" << std::endl; }
  102. };
  103.  
  104. struct Derived : public Base
  105. {
  106. void print() override { std::cout << "Derived::print" << std::endl; }
  107. };
  108.  
  109.  
  110. int main()
  111. {
  112. Pool<Derived> pool;
  113. Handle<Derived> d = pool.create();
  114. Handle<Base> b1 = d;
  115. Handle<Base> b2 = pool.create();
  116.  
  117.  
  118. if(b1)
  119. b1->print();
  120.  
  121. if(b2)
  122. b2->print();
  123.  
  124. b2 = d;
  125. b1.destroy();
  126.  
  127. if(b1)
  128. b1->print();
  129. else
  130. std::cout << "b1 is gone" << std::endl;
  131.  
  132. if(b2)
  133. b2->print();
  134. else
  135. std::cout << "b2 is gone" << std::endl;
  136.  
  137.  
  138. //Handle<Derived> d2 = b2; // Compile error - which is expected
  139. Handle<Derived> d2 = static_handle_cast<Derived>(b2);
  140. if(d2)
  141. d2->print();
  142. }
Success #stdin #stdout 0s 3460KB
stdin
Standard input is empty
stdout
Derived::print
Derived::print
b1 is gone
b2 is gone