fork download
  1. #include <iostream>
  2.  
  3. /// In header
  4. #include <cassert>
  5. #include <vector>
  6.  
  7. template <class, size_t> class BaseT;
  8.  
  9. class Base {
  10. template <class, size_t> friend class BaseT;
  11. public:
  12.  
  13. int get() const; // -> Implement: 'int getImpl() const' in Derived
  14.  
  15. void set(int i); // = 0 -> Implement: 'void setImpl(int i)' in Derived
  16.  
  17. private:
  18. struct VTable {
  19. typedef int (*Getter)(void const*);
  20. typedef void (*Setter)(void*, int);
  21.  
  22. VTable(): _get(0), _set(0) {}
  23.  
  24. Getter _get;
  25. Setter _set;
  26. };
  27.  
  28. static std::vector<VTable>& VT(); // defined in .cpp
  29.  
  30. explicit Base(size_t v): _v(v) {}
  31.  
  32. size_t _v;
  33. }; // class Base
  34.  
  35. template <class Derived, size_t Index>
  36. class BaseT: public Base {
  37. public:
  38. BaseT(): Base(Index) {
  39. static bool const _ = Register();
  40. (void)_;
  41. }
  42.  
  43. // Provide default implementation of getImpl
  44. int getImpl() const { return 0; }
  45.  
  46. // No default implementation setImpl
  47.  
  48. private:
  49. static int Get(void const* b) {
  50. Derived const* d = static_cast<Derived const*>(b);
  51. return d->getImpl();
  52. }
  53.  
  54. static void Set(void* b, int i) {
  55. Derived* d = static_cast<Derived*>(b);
  56. d->setImpl(i);
  57. }
  58.  
  59. static bool Register() {
  60. typedef Base::VTable VTable;
  61.  
  62. std::vector<VTable>& vt = Base::VT();
  63.  
  64. if (vt.size() <= Index) {
  65. vt.insert(vt.end(), Index - vt.size() + 1, VTable());
  66. } else {
  67. assert(vt[Index]._get == 0 && "Already registered VTable!");
  68. }
  69.  
  70. vt[Index]._get = &Get;
  71. vt[Index]._set = &Set;
  72.  
  73. return true;
  74. }
  75. }; // class BaseT
  76.  
  77. /// In source
  78. std::vector<Base::VTable>& Base::VT() {
  79. static std::vector<VTable> V;
  80. return V;
  81. } // Base::VT
  82.  
  83. int Base::get() const {
  84. return VT()[_v]._get(this);
  85. } // Base::get
  86.  
  87. void Base::set(int i) {
  88. return VT()[_v]._set(this, i);
  89. } // Base::set
  90.  
  91. // 4 must be unique within the hierarchy
  92. class Derived: public BaseT<Derived, 4> {
  93. template <class, size_t> friend class BaseT;
  94. public:
  95. Derived(): _i(0) {}
  96.  
  97. private:
  98. int getImpl() const { return _i; }
  99.  
  100. void setImpl(int i) { _i = i; }
  101.  
  102. int _i;
  103. }; // class Derived
  104.  
  105.  
  106. /// In action
  107. void print(Base const& b) { std::cout << b.get() << "\n"; }
  108. void set(Base& b, int i) { b.set(i); }
  109.  
  110. int main() {
  111. Derived d;
  112. set(d, 4);
  113. print(d);
  114. }
Success #stdin #stdout 0.02s 2816KB
stdin
Standard input is empty
stdout
4