list.hpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. #ifndef BOOST_MP11_LIST_HPP_INCLUDED
  2. #define BOOST_MP11_LIST_HPP_INCLUDED
  3. // Copyright 2015-2017 Peter Dimov.
  4. //
  5. // Distributed under the Boost Software License, Version 1.0.
  6. //
  7. // See accompanying file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt
  9. #include <boost/mp11/integral.hpp>
  10. #include <boost/mp11/detail/mp_list.hpp>
  11. #include <boost/mp11/detail/mp_is_list.hpp>
  12. #include <boost/mp11/detail/mp_append.hpp>
  13. #include <boost/mp11/detail/config.hpp>
  14. #include <type_traits>
  15. namespace boost
  16. {
  17. namespace mp11
  18. {
  19. // mp_list_c<T, I...>
  20. template<class T, T... I> using mp_list_c = mp_list<std::integral_constant<T, I>...>;
  21. // mp_is_list<L>
  22. // in detail/mp_is_list.hpp
  23. // mp_size<L>
  24. namespace detail
  25. {
  26. template<class L> struct mp_size_impl
  27. {
  28. // An error "no type named 'type'" here means that the argument to mp_size is not a list
  29. };
  30. template<template<class...> class L, class... T> struct mp_size_impl<L<T...>>
  31. {
  32. using type = mp_size_t<sizeof...(T)>;
  33. };
  34. } // namespace detail
  35. template<class L> using mp_size = typename detail::mp_size_impl<L>::type;
  36. // mp_empty<L>
  37. template<class L> using mp_empty = mp_bool< mp_size<L>::value == 0 >;
  38. // mp_assign<L1, L2>
  39. namespace detail
  40. {
  41. template<class L1, class L2> struct mp_assign_impl;
  42. template<template<class...> class L1, class... T, template<class...> class L2, class... U> struct mp_assign_impl<L1<T...>, L2<U...>>
  43. {
  44. using type = L1<U...>;
  45. };
  46. } // namespace detail
  47. template<class L1, class L2> using mp_assign = typename detail::mp_assign_impl<L1, L2>::type;
  48. // mp_clear<L>
  49. template<class L> using mp_clear = mp_assign<L, mp_list<>>;
  50. // mp_front<L>
  51. namespace detail
  52. {
  53. template<class L> struct mp_front_impl
  54. {
  55. // An error "no type named 'type'" here means that the argument to mp_front
  56. // is either not a list, or is an empty list
  57. };
  58. template<template<class...> class L, class T1, class... T> struct mp_front_impl<L<T1, T...>>
  59. {
  60. using type = T1;
  61. };
  62. } // namespace detail
  63. template<class L> using mp_front = typename detail::mp_front_impl<L>::type;
  64. // mp_pop_front<L>
  65. namespace detail
  66. {
  67. template<class L> struct mp_pop_front_impl
  68. {
  69. // An error "no type named 'type'" here means that the argument to mp_pop_front
  70. // is either not a list, or is an empty list
  71. };
  72. template<template<class...> class L, class T1, class... T> struct mp_pop_front_impl<L<T1, T...>>
  73. {
  74. using type = L<T...>;
  75. };
  76. } // namespace detail
  77. template<class L> using mp_pop_front = typename detail::mp_pop_front_impl<L>::type;
  78. // mp_first<L>
  79. template<class L> using mp_first = mp_front<L>;
  80. // mp_rest<L>
  81. template<class L> using mp_rest = mp_pop_front<L>;
  82. // mp_second<L>
  83. namespace detail
  84. {
  85. template<class L> struct mp_second_impl
  86. {
  87. // An error "no type named 'type'" here means that the argument to mp_second
  88. // is either not a list, or has fewer than two elements
  89. };
  90. template<template<class...> class L, class T1, class T2, class... T> struct mp_second_impl<L<T1, T2, T...>>
  91. {
  92. using type = T2;
  93. };
  94. } // namespace detail
  95. template<class L> using mp_second = typename detail::mp_second_impl<L>::type;
  96. // mp_third<L>
  97. namespace detail
  98. {
  99. template<class L> struct mp_third_impl
  100. {
  101. // An error "no type named 'type'" here means that the argument to mp_third
  102. // is either not a list, or has fewer than three elements
  103. };
  104. template<template<class...> class L, class T1, class T2, class T3, class... T> struct mp_third_impl<L<T1, T2, T3, T...>>
  105. {
  106. using type = T3;
  107. };
  108. } // namespace detail
  109. template<class L> using mp_third = typename detail::mp_third_impl<L>::type;
  110. // mp_push_front<L, T...>
  111. namespace detail
  112. {
  113. template<class L, class... T> struct mp_push_front_impl
  114. {
  115. // An error "no type named 'type'" here means that the first argument to mp_push_front is not a list
  116. };
  117. template<template<class...> class L, class... U, class... T> struct mp_push_front_impl<L<U...>, T...>
  118. {
  119. using type = L<T..., U...>;
  120. };
  121. } // namespace detail
  122. template<class L, class... T> using mp_push_front = typename detail::mp_push_front_impl<L, T...>::type;
  123. // mp_push_back<L, T...>
  124. namespace detail
  125. {
  126. template<class L, class... T> struct mp_push_back_impl
  127. {
  128. // An error "no type named 'type'" here means that the first argument to mp_push_back is not a list
  129. };
  130. template<template<class...> class L, class... U, class... T> struct mp_push_back_impl<L<U...>, T...>
  131. {
  132. using type = L<U..., T...>;
  133. };
  134. } // namespace detail
  135. template<class L, class... T> using mp_push_back = typename detail::mp_push_back_impl<L, T...>::type;
  136. // mp_rename<L, B>
  137. namespace detail
  138. {
  139. template<class A, template<class...> class B> struct mp_rename_impl
  140. {
  141. // An error "no type named 'type'" here means that the first argument to mp_rename is not a list
  142. };
  143. template<template<class...> class A, class... T, template<class...> class B> struct mp_rename_impl<A<T...>, B>
  144. {
  145. using type = B<T...>;
  146. };
  147. } // namespace detail
  148. template<class A, template<class...> class B> using mp_rename = typename detail::mp_rename_impl<A, B>::type;
  149. template<template<class...> class F, class L> using mp_apply = typename detail::mp_rename_impl<L, F>::type;
  150. template<class Q, class L> using mp_apply_q = typename detail::mp_rename_impl<L, Q::template fn>::type;
  151. // mp_replace_front<L, T>
  152. namespace detail
  153. {
  154. template<class L, class T> struct mp_replace_front_impl
  155. {
  156. // An error "no type named 'type'" here means that the first argument to mp_replace_front
  157. // is either not a list, or is an empty list
  158. };
  159. template<template<class...> class L, class U1, class... U, class T> struct mp_replace_front_impl<L<U1, U...>, T>
  160. {
  161. using type = L<T, U...>;
  162. };
  163. } // namespace detail
  164. template<class L, class T> using mp_replace_front = typename detail::mp_replace_front_impl<L, T>::type;
  165. // mp_replace_first<L, T>
  166. template<class L, class T> using mp_replace_first = typename detail::mp_replace_front_impl<L, T>::type;
  167. // mp_replace_second<L, T>
  168. namespace detail
  169. {
  170. template<class L, class T> struct mp_replace_second_impl
  171. {
  172. // An error "no type named 'type'" here means that the first argument to mp_replace_second
  173. // is either not a list, or has fewer than two elements
  174. };
  175. template<template<class...> class L, class U1, class U2, class... U, class T> struct mp_replace_second_impl<L<U1, U2, U...>, T>
  176. {
  177. using type = L<U1, T, U...>;
  178. };
  179. } // namespace detail
  180. template<class L, class T> using mp_replace_second = typename detail::mp_replace_second_impl<L, T>::type;
  181. // mp_replace_third<L, T>
  182. namespace detail
  183. {
  184. template<class L, class T> struct mp_replace_third_impl
  185. {
  186. // An error "no type named 'type'" here means that the first argument to mp_replace_third
  187. // is either not a list, or has fewer than three elements
  188. };
  189. template<template<class...> class L, class U1, class U2, class U3, class... U, class T> struct mp_replace_third_impl<L<U1, U2, U3, U...>, T>
  190. {
  191. using type = L<U1, U2, T, U...>;
  192. };
  193. } // namespace detail
  194. template<class L, class T> using mp_replace_third = typename detail::mp_replace_third_impl<L, T>::type;
  195. // mp_transform_front<L, F>
  196. namespace detail
  197. {
  198. template<class L, template<class...> class F> struct mp_transform_front_impl
  199. {
  200. // An error "no type named 'type'" here means that the first argument to mp_transform_front
  201. // is either not a list, or is an empty list
  202. };
  203. template<template<class...> class L, class U1, class... U, template<class...> class F> struct mp_transform_front_impl<L<U1, U...>, F>
  204. {
  205. using type = L<F<U1>, U...>;
  206. };
  207. } // namespace detail
  208. template<class L, template<class...> class F> using mp_transform_front = typename detail::mp_transform_front_impl<L, F>::type;
  209. template<class L, class Q> using mp_transform_front_q = mp_transform_front<L, Q::template fn>;
  210. // mp_transform_first<L, F>
  211. template<class L, template<class...> class F> using mp_transform_first = typename detail::mp_transform_front_impl<L, F>::type;
  212. template<class L, class Q> using mp_transform_first_q = mp_transform_first<L, Q::template fn>;
  213. // mp_transform_second<L, F>
  214. namespace detail
  215. {
  216. template<class L, template<class...> class F> struct mp_transform_second_impl
  217. {
  218. // An error "no type named 'type'" here means that the first argument to mp_transform_second
  219. // is either not a list, or has fewer than two elements
  220. };
  221. template<template<class...> class L, class U1, class U2, class... U, template<class...> class F> struct mp_transform_second_impl<L<U1, U2, U...>, F>
  222. {
  223. using type = L<U1, F<U2>, U...>;
  224. };
  225. } // namespace detail
  226. template<class L, template<class...> class F> using mp_transform_second = typename detail::mp_transform_second_impl<L, F>::type;
  227. template<class L, class Q> using mp_transform_second_q = mp_transform_second<L, Q::template fn>;
  228. // mp_transform_third<L, F>
  229. namespace detail
  230. {
  231. template<class L, template<class...> class F> struct mp_transform_third_impl
  232. {
  233. // An error "no type named 'type'" here means that the first argument to mp_transform_third
  234. // is either not a list, or has fewer than three elements
  235. };
  236. template<template<class...> class L, class U1, class U2, class U3, class... U, template<class...> class F> struct mp_transform_third_impl<L<U1, U2, U3, U...>, F>
  237. {
  238. using type = L<U1, U2, F<U3>, U...>;
  239. };
  240. } // namespace detail
  241. template<class L, template<class...> class F> using mp_transform_third = typename detail::mp_transform_third_impl<L, F>::type;
  242. template<class L, class Q> using mp_transform_third_q = mp_transform_third<L, Q::template fn>;
  243. } // namespace mp11
  244. } // namespace boost
  245. #endif // #ifndef BOOST_MP11_LIST_HPP_INCLUDED