fork(1) download
  1. #include <iostream>
  2. #include <set>
  3.  
  4. template <typename> class Registrable;
  5.  
  6. //
  7. // class Registry
  8. //
  9. class Registry {
  10. public:
  11. template <typename> friend class Registrable;
  12.  
  13. template <typename T>
  14. static T* Cast(void*);
  15.  
  16. private:
  17. struct TagType {};
  18.  
  19. using Key = std::pair<TagType const*, void*>;
  20. using Store = std::set<Key>;
  21.  
  22. template <typename T>
  23. static void Register(Registrable<T>* t);
  24.  
  25. template <typename T>
  26. static void Unregister(Registrable<T>* t);
  27.  
  28. static Store& Get();
  29. }; // class Registry
  30.  
  31. template <typename T>
  32. T* Registry::Cast(void* const pointer) {
  33. TagType const* const tag = &Registrable<T>::Tag;
  34.  
  35. if (Get().count(std::make_pair(tag, pointer)) == 0) { return nullptr; }
  36.  
  37. return static_cast<T*>(reinterpret_cast<Registrable<T>*>(pointer));
  38. }
  39.  
  40. template <typename T>
  41. void Registry::Register(Registrable<T>* t) {
  42. TagType const* const tag = &T::Tag;
  43. void* const pointer = reinterpret_cast<void*>(t);
  44.  
  45. Get().insert(std::make_pair(tag, pointer));
  46. }
  47.  
  48. template <typename T>
  49. void Registry::Unregister(Registrable<T>* t) {
  50. TagType const* const tag = &T::Tag;
  51. void* const pointer = reinterpret_cast<void*>(t);
  52.  
  53. Get().erase(std::make_pair(tag, pointer));
  54. }
  55.  
  56. Registry::Store& Registry::Get() { static Store S; return S; }
  57.  
  58. //
  59. // class Registrable
  60. //
  61. template <typename T>
  62. class Registrable {
  63. public:
  64. static Registry::TagType const Tag;
  65.  
  66. Registrable();
  67. ~Registrable();
  68.  
  69. Registrable(Registrable&&) = default;
  70. Registrable& operator=(Registrable&&) = default;
  71.  
  72. Registrable(Registrable const&) = default;
  73. Registrable& operator=(Registrable const&) = default;
  74. }; // class Registrable
  75.  
  76. template <typename T> Registry::TagType const Registrable<T>::Tag;
  77.  
  78. template <typename T>
  79. Registrable<T>::Registrable() { Registry::Register(this); }
  80.  
  81. template <typename T>
  82. Registrable<T>::~Registrable() { try { Registry::Register(this); } catch(...) {} }
  83.  
  84. //
  85. // Example
  86. //
  87. class Example: public Registrable<Example> {};
  88.  
  89. int main() {
  90. Example e;
  91. void* p = &e;
  92. void* q = &e + 1;
  93.  
  94. std::cout << &e << " " << p << " " << Registry::Cast<Example>(p) << "\n";
  95. std::cout << (&e + 1) << " " << q << " " << Registry::Cast<Example>(q) << "\n";
  96.  
  97. return 0;
  98. }
Success #stdin #stdout 0s 3432KB
stdin
Standard input is empty
stdout
0xbffe0c2f 0xbffe0c2f 0xbffe0c2f
0xbffe0c30 0xbffe0c30 0