fork download
  1. #include <iostream>
  2. #include <type_traits>
  3. #include <cstddef>
  4. #include <cstdint>
  5. #include <utility>
  6.  
  7. template <typename Type>
  8. struct LinkExtension;
  9.  
  10. template <typename Type>
  11. struct TypeEx {
  12. using Extension = typename LinkExtension<Type>::Type;
  13.  
  14. alignas(Type) uint8_t objectData[sizeof(Type)];
  15. alignas(Extension) uint8_t extensionData[sizeof(Extension)];
  16.  
  17. Type* getObject() { return reinterpret_cast<Type*>(objectData); }
  18. const Type* getObject() const { return reinterpret_cast<const Type*>(objectData); }
  19. Extension* getExtension() { return reinterpret_cast<Extension*>(extensionData); }
  20. const Extension* getExtension() const { return reinterpret_cast<const Extension*>(extensionData); }
  21.  
  22. template <class... Args>
  23. TypeEx(Args&&... args)
  24. {
  25. new (objectData) Type(std::forward<Args>(args)...);
  26. new (extensionData) Extension();
  27. }
  28. ~TypeEx()
  29. {
  30. getObject()->~Type();
  31. getExtension()->~Extension();
  32. }
  33. TypeEx(const TypeEx&) = delete;
  34. TypeEx& operator = (const TypeEx&) = delete;
  35. };
  36.  
  37. template <typename Type, class... Args>
  38. Type* createObjectEx(Args&&... args)
  39. {
  40. TypeEx<Type>* retVal = new TypeEx<Type>(std::forward<Args>(args)...);
  41. return retVal->getObject();
  42. }
  43.  
  44. template <typename Type>
  45. typename LinkExtension<Type>::Type& getObjectEx(Type* obj)
  46. {
  47. static_assert(std::is_standard_layout<TypeEx<Type>>::value, "Oops");
  48. static_assert(offsetof(TypeEx<Type>, objectData) == 0, "Oops");
  49. TypeEx<Type>* retVal = static_cast<TypeEx<Type>*>((void*)obj);
  50. return *(retVal->getExtension());
  51. }
  52.  
  53. template <typename Type>
  54. const typename LinkExtension<Type>::Type& getObjectEx(const Type* obj)
  55. {
  56. static_assert(std::is_standard_layout<TypeEx<Type>>::value, "Oops");
  57. static_assert(offsetof(TypeEx<Type>, objectData) == 0, "Oops");
  58. const TypeEx<Type>* retVal = static_cast<const TypeEx<Type>*>((const void*)obj);
  59. return *(retVal->getExtension());
  60. }
  61.  
  62. template <typename Type>
  63. void deleteObjectEx(const Type* obj)
  64. {
  65. const TypeEx<Type>* objectEx = static_cast<const TypeEx<Type>*>((const void*)obj);
  66. delete objectEx;
  67. }
  68.  
  69.  
  70. class MyClass {
  71. public:
  72. virtual ~MyClass() = default;
  73. };
  74. struct MyClassExtension {
  75. int a;
  76. int b;
  77. };
  78. template <>
  79. struct LinkExtension<MyClass> {
  80. typedef MyClassExtension Type;
  81. };
  82.  
  83. void printExtension(MyClass* object);
  84. int main() {
  85. MyClass* object = createObjectEx<MyClass>();
  86. MyClassExtension& extension = getObjectEx(object);
  87. extension.a = 1;
  88. extension.b = 2;
  89. printExtension(object);
  90. deleteObjectEx(object);
  91.  
  92. TypeEx<MyClass> objectEx;
  93. objectEx.getExtension()->a = 3;
  94. objectEx.getExtension()->b = 4;
  95. printExtension(objectEx.getObject());
  96. }
  97.  
  98. void printExtension(MyClass* object)
  99. {
  100. MyClassExtension& extension = getObjectEx(object);
  101. std::cout << extension.a << ' ' << extension.b << std::endl;
  102. }
  103.  
Success #stdin #stdout 0s 16064KB
stdin
Standard input is empty
stdout
1 2
3 4