General Purpose library for Freestanding C++ and POSIX systems
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

233 rivejä
5.0 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 = typename either<idx==sizeof...(rest),T,typename r_index_at<idx,rest...>::type>::type;
  84. };
  85. template<typename T, typename U, typename ...rest>
  86. constexpr std::size_t max_size()
  87. {
  88. if constexpr (sizeof...(rest) == 0)
  89. {
  90. return gp::max(sizeof(T),sizeof(U));
  91. }
  92. else
  93. {
  94. return max_size<
  95. typename either<
  96. ( sizeof(T) > sizeof(U) ),
  97. T,
  98. U
  99. >::type,
  100. rest...>();
  101. }
  102. }
  103. template<typename T>
  104. struct remove_reference
  105. {
  106. using type = T;
  107. };
  108. template<typename T>
  109. struct remove_reference<T&>
  110. {
  111. using type = T;
  112. };
  113. template<typename T>
  114. struct remove_reference<T&&>
  115. {
  116. using type = T;
  117. };
  118. template<typename T>
  119. struct has_size_interface
  120. {
  121. private:
  122. typedef std::true_type yes;
  123. typedef std::false_type no;
  124. template<typename U, size_t (U::*f)() const> struct SFINAE{};
  125. template<class C> static yes test(SFINAE<C,&C::size>*);
  126. template<class C> static no test(...);
  127. public:
  128. static constexpr bool value = std::is_same<yes,decltype(test<T>(nullptr))>::value;
  129. };
  130. template<typename T>
  131. struct has_begin_interface
  132. {
  133. private:
  134. typedef std::true_type yes;
  135. typedef std::false_type no;
  136. template<typename U, auto (U::*f)() const> struct SFINAE{};
  137. template<class C> static yes test(SFINAE<C,&C::begin>*);
  138. template<class C> static no test(...);
  139. public:
  140. static constexpr bool value = std::is_same<yes,decltype(test<T>(nullptr))>::value;
  141. };
  142. template<typename T>
  143. struct has_end_interface
  144. {
  145. private:
  146. typedef std::true_type yes;
  147. typedef std::false_type no;
  148. template<typename U, auto (U::*f)() const> struct SFINAE{};
  149. template<class C> static yes test(SFINAE<C,&C::end>*);
  150. template<class C> static no test(...);
  151. public:
  152. static constexpr bool value = std::is_same<yes,decltype(test<T>(nullptr))>::value;
  153. };
  154. template<typename T>
  155. using has_range_interface = constexpr_all_of<has_begin_interface<T>::value,has_end_interface<T>::value>;
  156. template<typename T>
  157. using has_measurable_range_interface = constexpr_all_of<has_range_interface<T>::value,has_size_interface<T>::value>;
  158. template<typename T>
  159. struct has_allocate_interface
  160. {
  161. private:
  162. typedef std::true_type yes;
  163. typedef std::false_type no;
  164. template<typename U, void* (U::*f)(size_t) const> struct SFINAE{};
  165. template<class C> static yes test(SFINAE<C,&C::allocate>*);
  166. template<class C> static no test(...);
  167. public:
  168. static constexpr bool value = std::is_same<yes,decltype(test<T>(nullptr))>::value;
  169. };
  170. template<typename T>
  171. struct has_deallocate_interface
  172. {
  173. private:
  174. typedef std::true_type yes;
  175. typedef std::false_type no;
  176. template<typename U, void (U::*f)(void*) const> struct SFINAE{};
  177. template<class C> static yes test(SFINAE<C,&C::deallocate>*);
  178. template<class C> static no test(...);
  179. public:
  180. static constexpr bool value = std::is_same<yes,decltype(test<T>(nullptr))>::value;
  181. };
  182. template<typename T>
  183. using has_allocator_interface = constexpr_all_of<has_allocate_interface<T>::value,has_deallocate_interface<T>::value>;
  184. }