General Purpose library for Freestanding C++ and POSIX systems
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

222 linhas
6.0 KiB

  1. #pragma once
  2. #include "gp_config.hpp"
  3. #include <gp/algorithm/tmp_manip.hpp>
  4. #include "gp/allocator/dummy.hpp"
  5. #include "gp/exception.hpp"
  6. #include "gp/function.hpp"
  7. #include "gp/memory.hpp"
  8. #include <type_traits>
  9. #include <new>
  10. namespace gp{
  11. template<typename ...T>
  12. class fixed_variant final {
  13. std::size_t index = std::numeric_limits<std::size_t>::max();
  14. char buffer[max_size<T...>()];
  15. gp::function<void(void*, void*)> cpytor = [](void*, void*){};
  16. gp::function<void(void*, void*)> mvtor = [](void*, void*){};
  17. gp::function<void(void*)> dtor = [](void*){};
  18. static_assert(all_of_fixed_size<T...>::value, "not fixed");
  19. public:
  20. template<typename U>//, typename std::enable_if<list_contains_class<U,T...>::value,int>::type>
  21. constexpr fixed_variant(U& value)
  22. : index{r_index_of<U, T...>::value}
  23. {
  24. new(buffer) U(value);
  25. dtor = gp::function<void(void*)>([](void* thing){((U*)thing)->~U();});
  26. cpytor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(*(U*)src);});
  27. mvtor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(gp::move(*(U*)src));});
  28. }
  29. template<typename U>//, typename std::enable_if<list_contains_class<U,T...>::value,int>::type>
  30. constexpr fixed_variant(U&& value)
  31. : index{r_index_of<U, T...>::value}
  32. {
  33. new(buffer) U(std::move(value));
  34. dtor = gp::function<void(void*)>([](void* thing){((U*)thing)->~U();});
  35. cpytor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(*(U*)src);});
  36. mvtor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(gp::move(*(U*)src));});
  37. }
  38. constexpr fixed_variant(fixed_variant& oth)
  39. : index{oth.index}
  40. , dtor{oth.dtor}
  41. , cpytor{oth.cpytor}
  42. , mvtor{oth.mvtor}
  43. {
  44. cpytor(oth.buffer, buffer);
  45. }
  46. template<typename U>
  47. constexpr size_t alt() const {
  48. return r_index_of<U, T...>::value;
  49. }
  50. size_t type() const {
  51. return index;
  52. }
  53. void operator=(fixed_variant& value)
  54. {
  55. if(index != std::numeric_limits<std::size_t>::max())
  56. {
  57. dtor((void*)buffer);
  58. }
  59. index = value.index;
  60. cpytor = value.cpytor;
  61. dtor = value.dtor;
  62. mvtor(value.buffer, buffer);
  63. }
  64. template<typename U, typename std::enable_if<list_contains_class<U,T...>::value,int>::type>
  65. void operator=(U& value)
  66. {
  67. if(index != std::numeric_limits<std::size_t>::max())
  68. {
  69. dtor((void*)buffer);
  70. }
  71. index = r_index_of<U, T...>::value;
  72. new(buffer) U(value);
  73. dtor = gp::function([](void* thing){((U*)thing)->~U();});
  74. cpytor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(*(U*)src);});
  75. mvtor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(gp::move(*(U*)src));});
  76. }
  77. template<typename U, typename std::enable_if<list_contains_class<U,T...>::value,int>::type>
  78. void operator=(U&& value)
  79. {
  80. if(index != std::numeric_limits<std::size_t>::max())
  81. {
  82. dtor((void*)buffer);
  83. }
  84. index = r_index_of<U, T...>::value;
  85. new(buffer) U(std::move(value));
  86. dtor = gp::function([](void* thing){((U*)thing)->~U();});
  87. cpytor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(*(U*)src);});
  88. mvtor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(gp::move(*(U*)src));});
  89. }
  90. ~fixed_variant()
  91. {
  92. if(index != std::numeric_limits<std::size_t>::max())
  93. {
  94. dtor((void*)buffer);
  95. }
  96. }
  97. template<typename U>
  98. constexpr U& value()
  99. {
  100. if constexpr (gp_config::has_exceptions)
  101. {
  102. if(r_index_of<U, T...>::value != index)
  103. {
  104. throw bad_variant_access<U>{};
  105. }
  106. }
  107. return *reinterpret_cast<U*>(buffer);
  108. }
  109. template<typename U>
  110. constexpr U& is_a()
  111. {
  112. if(r_index_of<U, T...>::value == index)
  113. {
  114. return true;
  115. }
  116. else
  117. {
  118. return false;
  119. }
  120. }
  121. };
  122. /*template<typename allocator_t = gp_config::memory_module::default_allocator, typename ...T>
  123. class variant{
  124. std::size_t index = std::numeric_limits<std::size_t>::max();
  125. void* ptr;
  126. gp::function<void(void*)> dtor = [](void*){};
  127. allocator_t allocator;
  128. public:
  129. template<typename U, typename std::enable_if<list_contains_class<U,T...>::value,int>::type>
  130. constexpr variant(U& value)
  131. : index{r_index_of<U, T...>::value}
  132. {
  133. ptr = (void*)new(allocator.allocate(sizeof(U))) U(value);
  134. dtor = gp::function([](void* thing){((U*)thing)->~U();}); // TODO:replae with delete(p,t)
  135. }
  136. template<typename U, typename std::enable_if<list_contains_class<U,T...>::value,int>::type>
  137. constexpr variant(U&& value)
  138. : index{r_index_of<U, T...>::value}
  139. {
  140. ptr = (void*)new(allocator.allocate(sizeof(U))) U(std::move(value));
  141. dtor = gp::function([](void* thing){((U*)thing)->~U();}); // TODO:replae with delete(p,t)
  142. }
  143. template<typename U, typename std::enable_if<list_contains_class<U,T...>::value,int>::type>
  144. void operator=(U& value)
  145. {
  146. if(index != std::numeric_limits<std::size_t>::max())
  147. {
  148. dtor(ptr);
  149. allocator.deallocate(ptr);
  150. }
  151. index = r_index_of<U, T...>::value;
  152. ptr = (void*)new(allocator.allocate(sizeof(U))) U(value);
  153. dtor = gp::function([](void* thing){((U*)thing)->~U();}); // TODO:replae with delete(p,t)
  154. }
  155. template<typename U, typename std::enable_if<list_contains_class<U,T...>::value,int>::type>
  156. void operator=(U&& value)
  157. {
  158. if(index != std::numeric_limits<std::size_t>::max())
  159. {
  160. dtor(ptr);
  161. allocator.deallocate(ptr);
  162. }
  163. index = r_index_of<U, T...>::value;
  164. ptr = (void*)new(allocator.allocate(sizeof(U))) U(std::move(value));
  165. dtor = gp::function([](void* thing){((U*)thing)->~U();}); // TODO: replace with delete(p, t)
  166. }
  167. ~variant()
  168. {
  169. if(index != std::numeric_limits<std::size_t>::max())
  170. {
  171. dtor(ptr);
  172. allocator.deallocate(ptr);
  173. }
  174. }
  175. template<typename U>
  176. constexpr U& value()
  177. {
  178. if constexpr (gp_config::has_exceptions)
  179. {
  180. if(r_index_of<U, T...>::value != index)
  181. {
  182. throw bad_variant_access<U>{};
  183. }
  184. }
  185. return *reinterpret_cast<U*>(ptr);
  186. }
  187. template<typename U>
  188. constexpr U& is_a()
  189. {
  190. if(r_index_of<U, T...>::value == index)
  191. {
  192. return true;
  193. }
  194. else
  195. {
  196. return false;
  197. }
  198. }
  199. };*/
  200. }