Guest User

Untitled

a guest
Nov 20th, 2018
100
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.71 KB | None | 0 0
  1. namespace detail
  2. {
  3. class VariantHelper
  4. {
  5. public:
  6. typedef void(*DestructFunc)(void*);
  7. typedef void(*CopyFunc)(const void*, void*);
  8. typedef void(*MoveFunc)(void*, void*);
  9. typedef std::wstring(*ToStringFunc)(const void*);
  10.  
  11. struct FuncPointers
  12. {
  13. FuncPointers(DestructFunc destruct, CopyFunc copy, MoveFunc move, ToStringFunc toString)
  14. : Destruct(destruct)
  15. , Copy(copy)
  16. , Move(move)
  17. , ToString(toString)
  18. {
  19. }
  20.  
  21. DestructFunc Destruct;
  22. CopyFunc Copy;
  23. MoveFunc Move;
  24. ToStringFunc ToString;
  25. };
  26.  
  27. template <typename T>
  28. static const FuncPointers * GetFuncPointers()
  29. {
  30. static FuncPointers funcPointers(
  31. GetDestructFunc<T>(),
  32. GetCopyFunc<T>(),
  33. GetMoveFunc<T>(),
  34. GetToStringFunc<T>());
  35. return &funcPointers;
  36. }
  37.  
  38. private:
  39. template <typename T>
  40. static DestructFunc GetDestructFunc()
  41. {
  42. static auto destruct = [](void* storage)
  43. {
  44. reinterpret_cast<T*>(storage)->~T();
  45. };
  46. return destruct;
  47. }
  48.  
  49. template <typename T>
  50. static CopyFunc GetCopyFunc()
  51. {
  52. static auto copy = [](const void* oldStorage, void* newStorage)
  53. {
  54. new (newStorage) T(*reinterpret_cast<const T*>(oldStorage));
  55. };
  56. return copy;
  57. }
  58.  
  59. template <typename T>
  60. static MoveFunc GetMoveFunc()
  61. {
  62. static auto move = [](void* oldStorage, void* newStorage)
  63. {
  64. new (newStorage) T(std::move(*reinterpret_cast<T*>(oldStorage)));
  65. };
  66. return move;
  67. }
  68.  
  69. template <typename T>
  70. static ToStringFunc GetToStringFunc()
  71. {
  72. static auto toString = [](const void* storage)
  73. {
  74. std::wstring str;
  75. // Write (*reinterpret_cast<const T*>(storage)) in a string representation
  76. return str;
  77. };
  78. return toString;
  79. }
  80. };
  81. }
  82.  
  83. /// <summary>
  84. /// Variant implementation.
  85. /// </summary>
  86. template <typename ...Types>
  87. class VariantValue
  88. {
  89. public:
  90. VariantValue()
  91. : helperFuncs_(nullptr)
  92. {
  93. }
  94.  
  95. VariantValue(VariantValue const& other)
  96. : helperFuncs_(other.helperFuncs_)
  97. {
  98. if (IsValid())
  99. {
  100. helperFuncs_->Copy(&other.storage_, &storage_);
  101. }
  102. }
  103.  
  104. VariantValue(VariantValue&& other)
  105. : helperFuncs_(other.helperFuncs_)
  106. {
  107. if (IsValid())
  108. {
  109. helperFuncs_->Move(&other.storage_, &storage_);
  110. }
  111. }
  112.  
  113. VariantValue& operator=(VariantValue const& other)
  114. {
  115. if (IsValid())
  116. {
  117. helperFuncs_->Destruct(&storage_);
  118. }
  119.  
  120. helperFuncs_ = other.helperFuncs_;
  121.  
  122. if (IsValid())
  123. {
  124. helperFuncs_->Copy(&other.storage_, &storage_);
  125. }
  126. return *this;
  127. }
  128.  
  129. ~VariantValue()
  130. {
  131. if (IsValid())
  132. {
  133. helperFuncs_->Destruct(&storage_);
  134. }
  135. }
  136.  
  137. /// <summary>
  138. /// Sets the value in the variant.
  139. /// </summary>
  140. template <class FieldT>
  141. void Set(FieldT&& value)
  142. {
  143. InPlace(std::forward<FieldT>(value));
  144. SetInternal<FieldT>();
  145. }
  146.  
  147. /// <summary>
  148. /// Sets the value in the variant.
  149. /// </summary>
  150. template <class FieldT>
  151. void Set(FieldT const& value)
  152. {
  153. InPlace(value);
  154. SetInternal<FieldT>();
  155. }
  156.  
  157. /// <summary>
  158. /// Gets the value from the variant.
  159. /// </summary>
  160. template <class FieldT>
  161. FieldT const& Get() const
  162. {
  163. if (!IsValid())
  164. {
  165. throw std::bad_cast();
  166. }
  167.  
  168. return *reinterpret_cast<const FieldT*>(&storage_);
  169. }
  170.  
  171. /// <summary>
  172. /// Gets the value from the variant as a string.
  173. /// </summary>
  174. std::wstring ToString() const
  175. {
  176. if (!IsValid())
  177. {
  178. throw std::bad_cast();
  179. }
  180.  
  181. return helperFuncs_->ToString(&storage_);
  182. }
  183.  
  184. private:
  185. bool IsValid() const
  186. {
  187. return helperFuncs_;
  188. }
  189.  
  190. template <typename FieldT>
  191. void InPlace(FieldT&& value)
  192. {
  193. if (IsValid())
  194. {
  195. helperFuncs_->Destruct(&storage_);
  196. }
  197.  
  198. ::new (&storage_) FieldT(value);
  199. }
  200.  
  201. template <typename FieldT>
  202. void InPlace(FieldT const& value)
  203. {
  204. if (IsValid())
  205. {
  206. helperFuncs_->Destruct(&storage_);
  207. }
  208.  
  209. ::new (&storage_) FieldT(value);
  210. }
  211.  
  212. template <class FieldT>
  213. void SetInternal()
  214. {
  215. helperFuncs_ = detail::VariantHelper::GetFuncPointers<FieldT>();
  216. }
  217.  
  218. using Storage = typename std::aligned_union<0, Types...>::type;
  219.  
  220. Storage storage_;
  221. const detail::VariantHelper::FuncPointers* helperFuncs_;
  222. };
Add Comment
Please, Sign In to add comment