General Purpose library for Freestanding C++ and POSIX systems
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

244 líneas
5.1 KiB

  1. #pragma once
  2. #include <type_traits>
  3. #include <typeinfo>
  4. #include <cstddef>
  5. #include <limits>
  6. #include "gp/algorithm/min_max.hpp"
  7. namespace gp{
  8. template<bool cond, typename T, typename U>
  9. struct either
  10. {
  11. };
  12. template<typename T, typename U>
  13. struct either<true,T,U>
  14. {
  15. typedef T type;
  16. };
  17. template<typename T, typename U>
  18. struct either<false,T,U>
  19. {
  20. typedef U type;
  21. };
  22. template<bool first, bool ...list>
  23. struct constexpr_all_of
  24. {
  25. static constexpr bool value = first && constexpr_all_of<list...>::value;
  26. };
  27. template<bool first>
  28. struct constexpr_all_of<first>
  29. {
  30. static constexpr bool value = first;
  31. };
  32. template<bool first, bool ...list>
  33. struct constexpr_any_of
  34. {
  35. static constexpr bool value = first || constexpr_any_of<list...>::value;
  36. };
  37. template<bool first>
  38. struct constexpr_any_of<first>
  39. {
  40. static constexpr bool value = first;
  41. };
  42. template<typename T>
  43. constexpr bool is_fixed_size()
  44. {
  45. return std::is_final<T>::value
  46. || std::is_fundamental<T>::value;
  47. }
  48. template<typename T, typename ...rest>
  49. struct all_of_fixed_size
  50. {
  51. static constexpr bool value = is_fixed_size<T>() && all_of_fixed_size<rest...>::value;
  52. };
  53. template<typename T>
  54. struct all_of_fixed_size<T>
  55. {
  56. static constexpr bool value = is_fixed_size<T>();
  57. };
  58. template<typename Univ, typename T, typename ...rest>
  59. struct list_contains_class
  60. {
  61. static constexpr bool value = (
  62. std::is_same<T, Univ>::value
  63. ) || list_contains_class<Univ, rest...>::value;
  64. };
  65. template<typename Univ, typename T>
  66. struct list_contains_class<Univ, T>
  67. {
  68. static constexpr bool value = std::is_same<T, Univ>::value;
  69. };
  70. template<typename Univ, typename T, typename ...rest>
  71. struct r_index_of
  72. {
  73. static constexpr std::size_t value = std::is_same<T, Univ>::value ? sizeof...(rest) : r_index_of<Univ, rest...>::value;
  74. };
  75. template<typename Univ, typename T>
  76. struct r_index_of<Univ, T>
  77. {
  78. static constexpr std::size_t value = std::is_same<T, Univ>::value ? 0 : std::numeric_limits<std::size_t>::max();
  79. };
  80. template<size_t idx, typename T, typename ...rest>
  81. struct r_index_at
  82. {
  83. using type =
  84. typename either<
  85. idx==sizeof...(rest),
  86. T,
  87. typename r_index_at<idx,rest...>::type
  88. >::type;
  89. };
  90. template<typename U, typename ...rest>
  91. struct first_of {
  92. using type = U;
  93. };
  94. template<typename T, typename U, typename ...rest>
  95. constexpr std::size_t max_size()
  96. {
  97. if constexpr (sizeof...(rest) == 0)
  98. {
  99. return gp::max(sizeof(T),sizeof(U));
  100. }
  101. else
  102. {
  103. return max_size<
  104. typename either<
  105. ( sizeof(T) > sizeof(U) ),
  106. T,
  107. U
  108. >::type,
  109. rest...>();
  110. }
  111. }
  112. template<typename T>
  113. struct remove_reference
  114. {
  115. using type = T;
  116. };
  117. template<typename T>
  118. struct remove_reference<T&>
  119. {
  120. using type = T;
  121. };
  122. template<typename T>
  123. struct remove_reference<T&&>
  124. {
  125. using type = T;
  126. };
  127. template<typename T>
  128. struct has_size_interface
  129. {
  130. private:
  131. typedef std::true_type yes;
  132. typedef std::false_type no;
  133. template<typename U, size_t (U::*f)() const> struct SFINAE{};
  134. template<class C> static yes test(SFINAE<C,&C::size>*);
  135. template<class C> static no test(...);
  136. public:
  137. static constexpr bool value = std::is_same<yes,decltype(test<T>(nullptr))>::value;
  138. };
  139. template<typename T>
  140. struct has_begin_interface
  141. {
  142. private:
  143. typedef std::true_type yes;
  144. typedef std::false_type no;
  145. template<typename U, auto (U::*f)() const> struct SFINAE{};
  146. template<class C> static yes test(SFINAE<C,&C::begin>*);
  147. template<class C> static no test(...);
  148. public:
  149. static constexpr bool value = std::is_same<yes,decltype(test<T>(nullptr))>::value;
  150. };
  151. template<typename T>
  152. struct has_end_interface
  153. {
  154. private:
  155. typedef std::true_type yes;
  156. typedef std::false_type no;
  157. template<typename U, auto (U::*f)() const> struct SFINAE{};
  158. template<class C> static yes test(SFINAE<C,&C::end>*);
  159. template<class C> static no test(...);
  160. public:
  161. static constexpr bool value = std::is_same<yes,decltype(test<T>(nullptr))>::value;
  162. };
  163. template<typename T>
  164. using has_range_interface = constexpr_all_of<has_begin_interface<T>::value,has_end_interface<T>::value>;
  165. template<typename T>
  166. using has_measurable_range_interface = constexpr_all_of<has_range_interface<T>::value,has_size_interface<T>::value>;
  167. template<typename T>
  168. struct has_allocate_interface
  169. {
  170. private:
  171. typedef std::true_type yes;
  172. typedef std::false_type no;
  173. template<typename U, void* (U::*f)(size_t)> struct SFINAE{};
  174. template<class C> static yes test(SFINAE<C,&C::allocate>*);
  175. template<class C> static no test(...);
  176. public:
  177. static constexpr bool value = std::is_same<yes,decltype(test<T>(nullptr))>::value;
  178. };
  179. template<typename T>
  180. struct has_deallocate_interface
  181. {
  182. private:
  183. typedef std::true_type yes;
  184. typedef std::false_type no;
  185. template<typename U, bool (U::*f)(void*)> struct SFINAE{};
  186. template<class C> static yes test(SFINAE<C,&C::deallocate>*);
  187. template<class C> static no test(...);
  188. public:
  189. static constexpr bool value = std::is_same<yes,decltype(test<T>(nullptr))>::value;
  190. };
  191. template<typename T>
  192. using has_allocator_interface = constexpr_all_of<has_allocate_interface<T>::value,has_deallocate_interface<T>::value>;
  193. }