hl.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. // Copyright (C) 2020 T. Zachary Laine
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See
  4. // accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_PARSER_DETAIL_HL_HPP
  7. #define BOOST_PARSER_DETAIL_HL_HPP
  8. #include <boost/parser/config.hpp>
  9. #include <boost/parser/tuple.hpp>
  10. #include <boost/parser/detail/detection.hpp>
  11. #include <type_traits>
  12. #include <utility>
  13. namespace boost { namespace parser { namespace detail::hl {
  14. // Boost.Hana lite. These functions work with boost::hana::tuple and
  15. // std::tuple.
  16. struct forward
  17. {
  18. template<typename T>
  19. decltype(auto) operator()(T && t)
  20. {
  21. return (T &&) t;
  22. }
  23. };
  24. template<typename... Args>
  25. constexpr auto make_tuple(Args &&... args)
  26. {
  27. #if BOOST_PARSER_USE_STD_TUPLE
  28. return std::make_tuple((Args &&) args...);
  29. #else
  30. return hana::make_tuple((Args &&) args...);
  31. #endif
  32. }
  33. template<typename T, typename U>
  34. constexpr auto make_pair(T && t, U && u)
  35. {
  36. return hl::make_tuple((T &&) t, (U &&) u);
  37. }
  38. template<typename Tuple1, typename Tuple2>
  39. constexpr auto concat(Tuple1 const & t1, Tuple2 const & t2)
  40. {
  41. #if BOOST_PARSER_USE_STD_TUPLE
  42. return std::tuple_cat(t1, t2);
  43. #else
  44. // Hana's concat does not seem to do what it says on the tin.
  45. // Concatenating (int, string) with (double, int) yields (int, string,
  46. // double). I maybe don't understand it well enough.
  47. return hana::insert_range(t1, hana::size(t1), t2);
  48. #endif
  49. }
  50. // apply
  51. template<typename F, typename Tuple, std::size_t... I>
  52. constexpr auto
  53. apply_impl(F && f, Tuple && t, std::integer_sequence<std::size_t, I...>)
  54. -> decltype(((F &&) f)(parser::get((Tuple &&) t, llong<I>{})...))
  55. {
  56. return ((F &&) f)(parser::get((Tuple &&) t, llong<I>{})...);
  57. }
  58. template<
  59. typename F,
  60. typename Tuple,
  61. typename Enable = std::enable_if_t<detail::is_tuple<
  62. std::remove_cv_t<std::remove_reference_t<Tuple>>>{}>>
  63. constexpr auto apply(F && f, Tuple && t) -> decltype(hl::apply_impl(
  64. (F &&) f,
  65. (Tuple &&) t,
  66. std::make_integer_sequence<std::size_t, tuple_size_<Tuple>>{}))
  67. {
  68. return hl::apply_impl(
  69. (F &&) f,
  70. (Tuple &&) t,
  71. std::make_integer_sequence<std::size_t, tuple_size_<Tuple>>{});
  72. }
  73. // for_each
  74. template<typename F, typename Tuple, std::size_t... I>
  75. constexpr void for_each_impl(
  76. Tuple const & t, F && f, std::integer_sequence<std::size_t, I...>)
  77. {
  78. int _[] = {0, (f(parser::get(t, llong<I>{})), 0)...};
  79. (void)_;
  80. }
  81. template<
  82. typename F,
  83. typename Tuple,
  84. std::size_t... I,
  85. typename Enable = std::enable_if_t<!std::is_reference_v<Tuple>>>
  86. constexpr void
  87. for_each_impl(Tuple && t, F && f, std::integer_sequence<std::size_t, I...>)
  88. {
  89. int _[] = {0, (f(std::move(parser::get(t, llong<I>{}))), 0)...};
  90. (void)_;
  91. }
  92. template<typename F, typename... Args>
  93. constexpr void for_each(tuple<Args...> && t, F && f)
  94. {
  95. hl::for_each_impl(
  96. std::move(t),
  97. (F &&) f,
  98. std::make_integer_sequence<std::size_t, sizeof...(Args)>());
  99. }
  100. template<typename F, typename... Args>
  101. constexpr void for_each(tuple<Args...> const & t, F && f)
  102. {
  103. hl::for_each_impl(
  104. t,
  105. (F &&) f,
  106. std::make_integer_sequence<std::size_t, sizeof...(Args)>());
  107. }
  108. // transform
  109. template<int offset, typename F, typename Tuple, std::size_t... I>
  110. constexpr auto transform_impl(
  111. Tuple const & t, F && f, std::integer_sequence<std::size_t, I...>)
  112. {
  113. return tuple<
  114. std::decay_t<decltype(f(parser::get(t, llong<I + offset>{})))>...>{
  115. f(parser::get(t, llong<I + offset>{}))...};
  116. }
  117. template<
  118. int offset,
  119. typename F,
  120. typename Tuple,
  121. std::size_t... I,
  122. typename Enable = std::enable_if_t<!std::is_reference_v<Tuple>>>
  123. auto constexpr transform_impl(
  124. Tuple && t, F && f, std::integer_sequence<std::size_t, I...>)
  125. {
  126. return tuple<std::decay_t<decltype(
  127. f(std::move(parser::get(t, llong<I + offset>{}))))>...>{
  128. f(std::move(parser::get(t, llong<I + offset>{})))...};
  129. }
  130. template<typename F, typename... Args>
  131. constexpr auto transform(tuple<Args...> && t, F && f)
  132. {
  133. return hl::transform_impl<0>(
  134. std::move(t),
  135. (F &&) f,
  136. std::make_integer_sequence<std::size_t, sizeof...(Args)>());
  137. }
  138. template<typename F, typename... Args>
  139. constexpr auto transform(tuple<Args...> const & t, F && f)
  140. {
  141. return hl::transform_impl<0>(
  142. t,
  143. (F &&) f,
  144. std::make_integer_sequence<std::size_t, sizeof...(Args)>());
  145. }
  146. // fold_left
  147. template<std::size_t I, std::size_t N>
  148. struct fold_left_dispatch
  149. {
  150. template<typename F, typename State, typename... Args>
  151. constexpr static auto
  152. call(tuple<Args...> const & t, State && s, F const & f)
  153. {
  154. return fold_left_dispatch<I + 1, N>::call(
  155. t, f((State &&) s, parser::get(t, llong<I>{})), f);
  156. }
  157. };
  158. template<std::size_t I>
  159. struct fold_left_dispatch<I, I>
  160. {
  161. template<typename F, typename State, typename... Args>
  162. constexpr static auto
  163. call(tuple<Args...> const & t, State && s, F const & f)
  164. {
  165. return (State &&) s;
  166. }
  167. };
  168. template<typename F, typename State, typename... Args>
  169. constexpr auto fold_left(tuple<Args...> const & t, State && s, F const & f)
  170. {
  171. return hl::fold_left_dispatch<0, sizeof...(Args)>::call(
  172. t, (State &&) s, (F &&) f);
  173. }
  174. // size
  175. template<typename... Args>
  176. constexpr auto size(tuple<Args...> const & t)
  177. {
  178. return llong<sizeof...(Args)>{};
  179. }
  180. template<typename... Args>
  181. constexpr auto size_minus_one(tuple<Args...> const & t)
  182. {
  183. return llong<sizeof...(Args) - 1>{};
  184. }
  185. // contains
  186. template<typename T, typename U>
  187. using comparable = decltype(std::declval<T>() == std::declval<U>());
  188. struct typesafe_equals
  189. {
  190. template<typename T, typename U>
  191. constexpr bool operator()(T const & t, U const & u)
  192. {
  193. if constexpr (detail::is_detected_v<comparable, T, U>) {
  194. return t == u;
  195. } else {
  196. return false;
  197. }
  198. }
  199. };
  200. template<typename T, typename Tuple, std::size_t... I>
  201. constexpr bool contains_impl(
  202. Tuple const & t, T const & x, std::integer_sequence<std::size_t, I...>)
  203. {
  204. typesafe_equals eq;
  205. (void)eq;
  206. return (eq(parser::get(t, llong<I>{}), x) || ...);
  207. }
  208. template<typename T, typename... Args>
  209. constexpr bool contains(tuple<Args...> const & t, T const & x)
  210. {
  211. return contains_impl(
  212. t, x, std::make_integer_sequence<std::size_t, sizeof...(Args)>());
  213. }
  214. // front, back
  215. template<typename Arg, typename... Args>
  216. constexpr decltype(auto) front(tuple<Arg, Args...> const & t)
  217. {
  218. return parser::get(t, llong<0>{});
  219. }
  220. template<typename Arg, typename... Args>
  221. constexpr decltype(auto) back(tuple<Arg, Args...> const & t)
  222. {
  223. return parser::get(t, llong<sizeof...(Args)>{});
  224. }
  225. // drop_front
  226. template<typename Arg, typename... Args>
  227. constexpr auto drop_front(tuple<Arg, Args...> && t)
  228. {
  229. return hl::transform_impl<1>(
  230. std::move(t),
  231. forward{},
  232. std::make_integer_sequence<std::size_t, sizeof...(Args)>());
  233. }
  234. template<typename Arg, typename... Args>
  235. constexpr auto drop_front(tuple<Arg, Args...> const & t)
  236. {
  237. return hl::transform_impl<1>(
  238. t,
  239. forward{},
  240. std::make_integer_sequence<std::size_t, sizeof...(Args)>());
  241. }
  242. // drop_back
  243. template<typename Arg, typename... Args>
  244. constexpr auto drop_back(tuple<Arg, Args...> && t)
  245. {
  246. return hl::transform_impl<0>(
  247. std::move(t),
  248. forward{},
  249. std::make_integer_sequence<std::size_t, sizeof...(Args)>());
  250. }
  251. template<typename Arg, typename... Args>
  252. constexpr auto drop_back(tuple<Arg, Args...> const & t)
  253. {
  254. return hl::transform_impl<0>(
  255. t,
  256. forward{},
  257. std::make_integer_sequence<std::size_t, sizeof...(Args)>());
  258. }
  259. // first, second
  260. template<typename T, typename U>
  261. constexpr decltype(auto) first(tuple<T, U> const & t)
  262. {
  263. return parser::get(t, llong<0>{});
  264. }
  265. template<typename T, typename U>
  266. constexpr decltype(auto) second(tuple<T, U> const & t)
  267. {
  268. return parser::get(t, llong<1>{});
  269. }
  270. // zip
  271. template<std::size_t I, typename... Tuples>
  272. constexpr decltype(auto) make_zip_elem(Tuples const &... ts)
  273. {
  274. return hl::make_tuple(parser::get(ts, llong<I>{})...);
  275. }
  276. template<std::size_t... I, typename... Tuples>
  277. constexpr auto zip_impl(std::index_sequence<I...>, Tuples const &... ts)
  278. {
  279. return hl::make_tuple(hl::make_zip_elem<I>(ts...)...);
  280. }
  281. template<typename T>
  282. struct tuplesize;
  283. template<typename... Args>
  284. struct tuplesize<tuple<Args...>>
  285. {
  286. constexpr static std::size_t value = sizeof...(Args);
  287. };
  288. template<typename Tuple, typename... Tuples>
  289. constexpr auto zip(Tuple const & t, Tuples const &... ts)
  290. {
  291. return hl::zip_impl(
  292. std::make_integer_sequence<
  293. std::size_t,
  294. tuplesize<std::remove_reference_t<Tuple>>::value>(),
  295. t,
  296. ts...);
  297. }
  298. // append
  299. template<typename... Args, typename T>
  300. constexpr auto append(tuple<Args...> && t, T && x)
  301. {
  302. #if BOOST_PARSER_USE_STD_TUPLE
  303. return std::tuple_cat(std::move(t), std::make_tuple((T &&) x));
  304. #else
  305. return hana::append(std::move(t), (T &&) x);
  306. #endif
  307. }
  308. template<typename... Args, typename T>
  309. constexpr auto append(tuple<Args...> const & t, T && x)
  310. {
  311. #if BOOST_PARSER_USE_STD_TUPLE
  312. return std::tuple_cat(t, std::make_tuple((T &&) x));
  313. #else
  314. return hana::append(t, (T &&) x);
  315. #endif
  316. }
  317. // prepend
  318. template<typename... Args, typename T>
  319. constexpr auto prepend(tuple<Args...> && t, T && x)
  320. {
  321. #if BOOST_PARSER_USE_STD_TUPLE
  322. return std::tuple_cat(std::make_tuple((T &&) x), std::move(t));
  323. #else
  324. return hana::prepend(std::move(t), (T &&) x);
  325. #endif
  326. }
  327. template<typename... Args, typename T>
  328. constexpr auto prepend(tuple<Args...> const & t, T && x)
  329. {
  330. #if BOOST_PARSER_USE_STD_TUPLE
  331. return std::tuple_cat(std::make_tuple((T &&) x), t);
  332. #else
  333. return hana::prepend(t, (T &&) x);
  334. #endif
  335. }
  336. }}}
  337. #endif