Micro template library A library for building device drivers
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 

416 lignes
12 KiB

  1. /*!
  2. * \file utl/meta/basic.h
  3. * \brief Template meta-programming basic definitions
  4. */
  5. #ifndef __utl_meta_basic_h__
  6. #define __utl_meta_basic_h__
  7. #include <utl/core/impl.h>
  8. #include <type_traits>
  9. #include <utility>
  10. /*!
  11. * \ingroup meta
  12. * \defgroup basic Basic
  13. * Basic definitions
  14. */
  15. //! @{
  16. /*!
  17. * \ingroup basic
  18. * \defgroup meta_core Core
  19. * Core definitions
  20. */
  21. //! @{
  22. namespace utl {
  23. namespace meta {
  24. /*!
  25. * \brief meta's empty type
  26. *
  27. * utl::meta's nil type is not pure nil. It's a recursive "de-referencable nil.
  28. * Each time someone applies \c \::type to it, he gets back nil_. This way we can prevent
  29. * a lot of compilation errors in a wrong meta:: handling.
  30. */
  31. struct nil_ {
  32. using type = nil_;
  33. };
  34. //! Type alias for \c Tp::type.
  35. //! Is used to evaluate/extract return type of metafunctions
  36. //! \tparam Tp The metafunction to evaluate
  37. //! \return The inner \::type
  38. template <typename Tp>
  39. using eval = typename Tp::type;
  40. //! Type alias for \c Tp::type::value.
  41. //! Is used to evaluate/extract return value of metafunctions
  42. //! \tparam Tp The metafunction to evaluate
  43. //! \return The inner \::type::value
  44. template <typename Tp>
  45. using eval_v = typename eval<Tp>::value;
  46. //!
  47. //! integral_ is a holder class for a compile-time value of an integral type.
  48. //!
  49. //! Every Integral Constant is also a null-ary Metafunction, returning itself.\n
  50. //! An integral constant object is implicitly convertible to the corresponding
  51. //! run-time value of the wrapped integral type
  52. template <typename Tp, Tp v>
  53. using integral_ = std::integral_constant<Tp, v>;
  54. //! \name Wrappers for basic types
  55. //! @{
  56. //! bool_ type: integral constant wrapper for bool
  57. template<bool v>
  58. using bool_ = integral_<bool, v>;
  59. using true_ = bool_<true>; //!< The type used as a compile-time boolean with true value.
  60. using false_ = bool_<false>; //!< The type used as a compile-time boolean with false value.
  61. //! int8_ type: integral constant wrapper for \c int8_t
  62. template<int8_t v>
  63. using int8_ = integral_<int8_t, v>;
  64. //! uint8_ type: integral constant wrapper for \c uint8_t
  65. template<uint8_t v>
  66. using uint8_ = integral_<uint8_t, v>;
  67. //! int16_ type: integral constant wrapper for \c int16_t
  68. template<int16_t v>
  69. using int16_ = integral_<int16_t, v>;
  70. //! uint16_ type: integral constant wrapper for \c uint16_t
  71. template<uint16_t v>
  72. using uint16_ = integral_<uint16_t, v>;
  73. //! int32_ type: integral constant wrapper for \c int32_t
  74. template<int32_t v>
  75. using int32_ = integral_<int32_t, v>;
  76. //! uint32_ type: integral constant wrapper for \c uint32_t
  77. template<uint32_t v>
  78. using uint32_ = integral_<uint32_t, v>;
  79. //! char_ type: integral constant wrapper for \c char
  80. template<char v>
  81. using char_ = integral_<char, v>;
  82. //! int_ type: integral constant wrapper for \c int
  83. template<int v>
  84. using int_ = integral_<int, v>;
  85. //! long_ type: integral constant wrapper for \c long
  86. template<long v>
  87. using long_ = integral_<long, v>;
  88. //! index_ type: integral constant wrapper for \c index_t a.k.a std::size_t
  89. template<index_t v>
  90. using index_ = integral_<index_t, v>;
  91. //! size_ type: integral constant wrapper for \c size_t a.k.a std::size_t
  92. template<size_t v>
  93. using size_ = integral_<size_t, v>;
  94. //! The last position we can express for indexing
  95. using Npos = size_<index_t(-1)>;
  96. //! @}
  97. //! \name unevaluated expressions
  98. //! @{
  99. //! Computes the size of the type \p Tp.
  100. //! Complexity \f$ O(1) \f$.
  101. template <typename Tp>
  102. using sizeof_ = size_<sizeof(Tp)>;
  103. //! Computes the alignment required for any instance of the type \p Tp.
  104. //! Complexity \f$ O(1) \f$.
  105. template <typename Tp>
  106. using alignof_ = size_<alignof(Tp)>;
  107. //! @}
  108. //! \name integer sequence
  109. //! @{
  110. template< class Tp, Tp... Ints >
  111. using integer_sequence = std::integer_sequence<Tp, Ints...>;
  112. template<typename Tp, Tp Num>
  113. using make_integer_sequence = std::make_integer_sequence<Tp, Num>;
  114. //! Alias template index_sequence
  115. template<index_t... Idx>
  116. using index_sequence = integer_sequence<index_t, Idx...>;
  117. //! Alias template make_index_sequence
  118. template<index_t Num>
  119. using make_index_sequence = make_integer_sequence <index_t, Num>;
  120. //! Alias template index_sequence_for
  121. template<typename... Types>
  122. using index_sequence_for = make_index_sequence<sizeof...(Types)>;
  123. //! @}
  124. }}
  125. //!@}
  126. /*!
  127. * \ingroup basic
  128. * \defgroup selection Selection
  129. * Type selection support header
  130. */
  131. //! @{
  132. namespace utl {
  133. namespace meta{
  134. //! \name if implementation
  135. //! @{
  136. namespace details {
  137. template <bool If, typename...>
  138. struct if_c_ {
  139. using type = nil_; //< avoid ill formed result
  140. };
  141. template<typename Then>
  142. struct if_c_<true, Then> {
  143. using type = Then;
  144. };
  145. template<typename Then, typename Else>
  146. struct if_c_<true, Then, Else> {
  147. using type = Then;
  148. };
  149. template<typename Then, typename Else>
  150. struct if_c_<false, Then, Else> {
  151. using type = Else;
  152. };
  153. }
  154. //! Select one type or another depending on a compile-time Boolean.
  155. template <bool B, typename... Args>
  156. using if_c = eval<details::if_c_<B, Args...>>;
  157. //! Select one type or another depending on a compile-time Boolean type
  158. template <typename If, typename... Args>
  159. using if_ = if_c<If::type::value, Args...>;
  160. //! @}
  161. /*!
  162. * \name Named type selectors
  163. */
  164. //! @{
  165. //! Select the first type of a type sequence
  166. template <typename T1, typename ...> using first_of = T1;
  167. //! Select the second type of a type sequence
  168. template <typename T1, typename T2, typename ...> using second_of = T2;
  169. //! @}
  170. }}
  171. //! @}
  172. /*!
  173. * \ingroup basic
  174. * \defgroup logic_operations Logic Operations
  175. * logic operators and type relations support
  176. */
  177. //! @{
  178. namespace utl {
  179. namespace meta{
  180. /*!
  181. * \name Logical relation for types
  182. */
  183. //! @{
  184. //! Negate the *bool* constant parameter and return bool_
  185. template <bool B>
  186. using not_c = bool_<!B>;
  187. //! negate the bool_ parameter and return bool_
  188. template<typename Tp>
  189. using not_ = not_c<Tp::type::value>;
  190. //! \name OR implementation
  191. //! @{
  192. namespace details {
  193. template<typename...> struct _or_;
  194. template<>
  195. struct _or_<> : false_ { };
  196. template<typename T1>
  197. struct _or_<T1> : T1 { };
  198. template<typename T1, typename T2>
  199. struct _or_ <T1, T2>
  200. : if_<T1, T1, T2> { };
  201. template<typename T1, typename T2, typename T3, typename... Tn>
  202. struct _or_<T1, T2, T3, Tn...>
  203. : if_<T1, T1, _or_<T2, T3, Tn...>> { };
  204. }
  205. //! Operator or for bool_ types
  206. //! \tparam Ts Variadic args of type bool_
  207. //! \return Logical or as bool_
  208. template <typename... Ts>
  209. using or_ = eval<details::_or_<Ts...>>;
  210. //! @}
  211. //! \name AND implementation
  212. //! @{
  213. namespace details {
  214. template<typename...> struct _and_;
  215. template<>
  216. struct _and_<>
  217. : true_ { };
  218. template<typename T1>
  219. struct _and_ <T1>
  220. : T1 { };
  221. template<typename T1, typename T2>
  222. struct _and_<T1, T2>
  223. : if_<T1, T2, T1> { };
  224. template<typename T1, typename T2, typename T3, typename... Tn>
  225. struct _and_<T1, T2, T3, Tn...>
  226. : if_<T1, _and_<T2, T3, Tn...>, T1> { };
  227. }
  228. //! Operator and for bool_ types
  229. //! \tparam Ts Variadic args of type bool_
  230. //! \return Logical and as bool_
  231. template <typename... Ts>
  232. using and_ = eval<details::_and_<Ts...>>;
  233. //! @}
  234. //! \name same
  235. //! @{
  236. template<typename T1, typename T2>
  237. struct same_ : false_ { };
  238. template<typename Tp>
  239. struct same_ <Tp, Tp> : true_ { };
  240. template<typename T1, typename T2>
  241. using not_same_ = not_<eval<same_<T1, T2>>>;
  242. //! @}
  243. //! @}
  244. }}
  245. //! @}
  246. /*!
  247. * \ingroup basic
  248. * \defgroup integral_operators integral operators
  249. * Type arithmetic and operations
  250. */
  251. //! @{
  252. namespace utl {
  253. namespace meta {
  254. /*!
  255. * \name Math operations
  256. */
  257. //! @{
  258. //! Negation
  259. template <typename Tp>
  260. using negate = integral_<decltype(-Tp()), -Tp()>;
  261. //! Addition
  262. template <typename Tp1, typename Tp2>
  263. using add = integral_<
  264. decltype(Tp1() + Tp2()),
  265. Tp1() + Tp2()
  266. >;
  267. //! Multiplication
  268. template <typename Tp1, typename Tp2>
  269. using mult = integral_<
  270. decltype(Tp2() * Tp2()),
  271. Tp1() * Tp2()
  272. >;
  273. //! Division
  274. template <typename Tp1, typename Tp2>
  275. using divide = integral_<
  276. decltype(Tp2() / Tp2()),
  277. Tp1() / Tp2()
  278. >;
  279. //! Modulo
  280. template <typename Tp1, typename Tp2>
  281. using modulo = integral_<
  282. decltype(Tp1() % Tp2()),
  283. Tp1() % Tp2()
  284. >;
  285. //! Substruction
  286. template <typename Tp1, typename Tp2>
  287. using sub = add<Tp1, negate<Tp2>>;
  288. //! Increase
  289. template <typename Tp>
  290. using inc = add<Tp, int_<1>>;
  291. //! decrease
  292. template <typename Tp>
  293. using dec = add<Tp, int_<-1>>;
  294. //! @}
  295. /*!
  296. * \name Comparison operations
  297. */
  298. //! @{
  299. //! \return a true-valued Integral Constant if Tp1 and Tp2 are equal.
  300. template <typename Tp1, typename Tp2> using comp_eq = bool_<Tp1() == Tp2()>;
  301. //! \return a true-valued Integral Constant if Tp1 is less than Tp2.
  302. template <typename Tp1, typename Tp2> using comp_lt = bool_<(Tp1() < Tp2())>;
  303. //! Not equal
  304. template <typename Tp1, typename Tp2> using comp_ne = not_<comp_eq<Tp1, Tp2>>;
  305. //! Greater than
  306. template <typename Tp1, typename Tp2> using comp_gt = comp_lt <Tp2, Tp1>;
  307. //! Less or equal
  308. template <typename Tp1, typename Tp2> using comp_le = not_<comp_lt<Tp2, Tp1>>;
  309. //! Greater or equal
  310. template <typename Tp1, typename Tp2> using comp_ge = not_<comp_lt<Tp1, Tp2>>;
  311. //! @}
  312. /*!
  313. * \name Bitwise operations
  314. */
  315. //! @{
  316. //! \return bitwise not (~) operation of its argument.
  317. template <typename T> using bitnot_ = integral_<typename T::value_type, (typename T::value_type)(~T())>;
  318. //! \return bitwise and (&) operation of its arguments
  319. template <typename Tp1, typename Tp2>
  320. using bitand_ = integral_<decltype(Tp1() & Tp2()), Tp1() & Tp2()>;
  321. //! \return bitwise or (|) operation of its arguments.
  322. template <typename Tp1, typename Tp2>
  323. using bitor_ = integral_<decltype(Tp1() | Tp2()), Tp1() | Tp2()>;
  324. //! \return bitwise xor (^) operation of its arguments.
  325. template <typename Tp1, typename Tp2>
  326. using bitxor_ = integral_<decltype(Tp1() ^ Tp2()), Tp1() ^ Tp2()>;
  327. //! \return the result of bitwise shift left (<<) operation on Tp.
  328. template <typename Tp, typename shift>
  329. using shift_left = integral_<typename Tp::value_type, (typename Tp::value_type)(Tp() << shift())>;
  330. //! \return the result of bitwise shift right (>>) operation on Tp.
  331. template <typename Tp, typename shift>
  332. using shift_right = integral_<typename Tp::value_type, (typename Tp::value_type)(Tp() >> shift())>;
  333. //! @}
  334. }}
  335. //! @}
  336. //! @}
  337. #endif /* __utl_meta_basic_h__ */