xmeta_utils.hpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640
  1. /***************************************************************************
  2. * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
  3. * Copyright (c) QuantStack *
  4. * *
  5. * Distributed under the terms of the BSD 3-Clause License. *
  6. * *
  7. * The full license is in the file LICENSE, distributed with this software. *
  8. ****************************************************************************/
  9. #ifndef XTL_XMETA_UTILS_HPP
  10. #define XTL_XMETA_UTILS_HPP
  11. #include <cstddef>
  12. #include <cstdint>
  13. #include <type_traits>
  14. #include "xfunctional.hpp"
  15. #include "xtl_config.hpp"
  16. namespace xtl
  17. {
  18. // TODO move to a xutils if we have one
  19. // gcc 4.9 is affected by C++14 defect CGW 1558
  20. // see http://open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#1558
  21. template <class... T>
  22. struct make_void
  23. {
  24. using type = void;
  25. };
  26. template <class... T>
  27. using void_t = typename make_void<T...>::type;
  28. namespace mpl
  29. {
  30. /*************
  31. * mpl types *
  32. *************/
  33. template <class... T>
  34. struct vector
  35. {
  36. };
  37. template <bool B>
  38. using bool_ = std::integral_constant<bool, B>;
  39. template <std::size_t S>
  40. using size_t_ = std::integral_constant<std::size_t, S>;
  41. /*******
  42. * if_ *
  43. *******/
  44. template <bool B, class T, class F>
  45. struct if_c : std::conditional<B, T, F>
  46. {
  47. };
  48. template <bool B, class T, class F>
  49. using if_c_t = typename if_c<B, T, F>::type;
  50. template <class B, class T, class F>
  51. struct if_ : if_c<B::value, T, F>
  52. {
  53. };
  54. template <class B, class T, class F>
  55. using if_t = typename if_<B, T, F>::type;
  56. /***********
  57. * eval_if *
  58. ***********/
  59. template <bool B, class T, class F>
  60. struct eval_if_c
  61. {
  62. using type = typename T::type;
  63. };
  64. template <class T, class F>
  65. struct eval_if_c<false, T, F>
  66. {
  67. using type = typename F::type;
  68. };
  69. template <class B, class T, class F>
  70. struct eval_if : eval_if_c<B::value, T, F>
  71. {
  72. };
  73. template <class B, class T, class F>
  74. using eval_if_t = typename eval_if<B, T, F>::type;
  75. /********
  76. * cast *
  77. ********/
  78. namespace detail
  79. {
  80. template <class A, template <class...> class B>
  81. struct cast_impl;
  82. template <template <class...> class A, class... T, template <class...> class B>
  83. struct cast_impl<A<T...>, B>
  84. {
  85. using type = B<T...>;
  86. };
  87. }
  88. template <class A, template <class...> class B>
  89. struct cast : detail::cast_impl<A, B>
  90. {
  91. };
  92. template <class A, template <class...> class B>
  93. using cast_t = typename cast<A, B>::type;
  94. /********
  95. * size *
  96. ********/
  97. namespace detail
  98. {
  99. template <class L>
  100. struct size_impl;
  101. template <template <class...> class F, class... T>
  102. struct size_impl<F<T...>> : size_t_<sizeof...(T)>
  103. {
  104. };
  105. }
  106. template <class L>
  107. struct size : detail::size_impl<L>
  108. {
  109. };
  110. /*********
  111. * empty *
  112. *********/
  113. namespace detail
  114. {
  115. template <class L>
  116. struct empty_impl;
  117. template <template <class...> class F, class... T>
  118. struct empty_impl<F<T...>> : bool_<sizeof...(T) == std::size_t(0)>
  119. {
  120. };
  121. }
  122. template <class L>
  123. struct empty : detail::empty_impl<L>
  124. {
  125. };
  126. template <class L>
  127. using empty_t = typename empty<L>::type;
  128. /********
  129. * plus *
  130. ********/
  131. namespace detail
  132. {
  133. template <class... T>
  134. struct plus_impl;
  135. template <>
  136. struct plus_impl<> : size_t_<0>
  137. {
  138. };
  139. template <class T1, class... T>
  140. struct plus_impl<T1, T...> : size_t_<T1::value + plus_impl<T...>::value>
  141. {
  142. };
  143. }
  144. template <class... T>
  145. struct plus : detail::plus_impl<T...>
  146. {
  147. };
  148. /*********
  149. * count *
  150. *********/
  151. namespace detail
  152. {
  153. template <class L, class V>
  154. struct count_impl;
  155. template <template <class...> class L, class... T, class V>
  156. struct count_impl<L<T...>, V> : plus<std::is_same<T, V>...>
  157. {
  158. };
  159. }
  160. template <class L, class V>
  161. struct count : detail::count_impl<L, V>
  162. {
  163. };
  164. /************
  165. * count_if *
  166. ************/
  167. namespace detail
  168. {
  169. template <class L, template <class> class P>
  170. struct count_if_impl;
  171. template <template <class...> class L, class... T, template <class> class P>
  172. struct count_if_impl<L<T...>, P> : plus<P<T>...>
  173. {
  174. };
  175. }
  176. template <class L, template <class> class P>
  177. struct count_if : detail::count_if_impl<L, P>
  178. {
  179. };
  180. /************
  181. * index_of *
  182. ************/
  183. namespace detail
  184. {
  185. template <class L, class V>
  186. struct index_of_impl;
  187. template <template <class...> class L, class V>
  188. struct index_of_impl<L<>, V>
  189. {
  190. static constexpr size_t value = SIZE_MAX;
  191. };
  192. template <template <class...> class L, class... T, class V>
  193. struct index_of_impl<L<V, T...>, V>
  194. {
  195. static constexpr size_t value = 0u;
  196. };
  197. template <template <class...> class L, class U, class... T, class V>
  198. struct index_of_impl<L<U, T...>, V>
  199. {
  200. static constexpr size_t tmp = index_of_impl<L<T...>, V>::value;
  201. static constexpr size_t value = tmp == SIZE_MAX ? SIZE_MAX : 1u + tmp;
  202. };
  203. }
  204. template <class L, class T>
  205. struct index_of : detail::index_of_impl<L, T>
  206. {
  207. };
  208. /************
  209. * contains *
  210. ************/
  211. namespace detail
  212. {
  213. template <class L, class V>
  214. struct contains_impl;
  215. template <template <class...> class L, class V>
  216. struct contains_impl<L<>, V> : std::false_type
  217. {
  218. };
  219. template <template <class...> class L, class... T, class V>
  220. struct contains_impl<L<V, T...>, V> : std::true_type
  221. {
  222. };
  223. template <template <class...> class L, class U, class... T, class V>
  224. struct contains_impl<L<U, T...>, V> : contains_impl<L<T...>, V>
  225. {
  226. };
  227. }
  228. template <class L, class V>
  229. struct contains : detail::contains_impl<L, V>
  230. {
  231. };
  232. /*********
  233. * front *
  234. *********/
  235. namespace detail
  236. {
  237. template <class L>
  238. struct front_impl;
  239. template <template <class...> class L, class T, class... U>
  240. struct front_impl<L<T, U...>>
  241. {
  242. using type = T;
  243. };
  244. }
  245. template <class L>
  246. struct front : detail::front_impl<L>
  247. {
  248. };
  249. template <class L>
  250. using front_t = typename front<L>::type;
  251. /********
  252. * back *
  253. ********/
  254. namespace detail
  255. {
  256. template <class L>
  257. struct back_impl;
  258. template <template <class...> class L, class T>
  259. struct back_impl<L<T>>
  260. {
  261. using type = T;
  262. };
  263. // Compilation time improvement
  264. template <template <class...> class L, class T1, class T2>
  265. struct back_impl<L<T1, T2>>
  266. {
  267. using type = T2;
  268. };
  269. template <template <class...> class L, class T1, class T2, class T3>
  270. struct back_impl<L<T1, T2, T3>>
  271. {
  272. using type = T3;
  273. };
  274. template <template <class...> class L, class T1, class T2, class T3, class T4>
  275. struct back_impl<L<T1, T2, T3, T4>>
  276. {
  277. using type = T4;
  278. };
  279. template <template <class...> class L, class T, class... U>
  280. struct back_impl<L<T, U...>> : back_impl<L<U...>>
  281. {
  282. };
  283. }
  284. template <class L>
  285. struct back : detail::back_impl<L>
  286. {
  287. };
  288. template <class L>
  289. using back_t = typename back<L>::type;
  290. /**************
  291. * push_front *
  292. **************/
  293. namespace detail
  294. {
  295. template <class L, class... T>
  296. struct push_front_impl;
  297. template <template <class...> class L, class... U, class... T>
  298. struct push_front_impl<L<U...>, T...>
  299. {
  300. using type = L<T..., U...>;
  301. };
  302. }
  303. template <class L, class... T>
  304. struct push_front : detail::push_front_impl<L, T...>
  305. {
  306. };
  307. template <class L, class... T>
  308. using push_front_t = typename push_front<L, T...>::type;
  309. /*************
  310. * push_back *
  311. *************/
  312. namespace detail
  313. {
  314. template <class L, class... T>
  315. struct push_back_impl;
  316. template <template <class...> class L, class... U, class... T>
  317. struct push_back_impl<L<U...>, T...>
  318. {
  319. using type = L<U..., T...>;
  320. };
  321. }
  322. template <class L, class... T>
  323. struct push_back : detail::push_back_impl<L, T...>
  324. {
  325. };
  326. template <class L, class... T>
  327. using push_back_t = typename push_back<L, T...>::type;
  328. /*************
  329. * pop_front *
  330. *************/
  331. namespace detail
  332. {
  333. template <class L>
  334. struct pop_front_impl;
  335. template <template <class...> class L, class T, class... U>
  336. struct pop_front_impl<L<T, U...>>
  337. {
  338. using type = L<U...>;
  339. };
  340. }
  341. template <class L>
  342. struct pop_front : detail::pop_front_impl<L>
  343. {
  344. };
  345. template <class L>
  346. using pop_front_t = typename pop_front<L>::type;
  347. /*************
  348. * transform *
  349. *************/
  350. namespace detail
  351. {
  352. template <template <class...> class F, class L>
  353. struct transform_impl;
  354. template <template <class...> class F, template <class...> class L, class... T>
  355. struct transform_impl<F, L<T...>>
  356. {
  357. using type = L<F<T>...>;
  358. };
  359. }
  360. template <template <class...> class F, class L>
  361. struct transform : detail::transform_impl<F, L>
  362. {
  363. };
  364. template <template <class...> class F, class L>
  365. using transform_t = typename transform<F, L>::type;
  366. /*************
  367. * merge_set *
  368. *************/
  369. namespace detail
  370. {
  371. template <class S1, class S2>
  372. struct merge_set_impl;
  373. template <template <class...> class L, class... T>
  374. struct merge_set_impl<L<T...>, L<>>
  375. {
  376. using type = L<T...>;
  377. };
  378. template <template <class...> class L, class... T, class U1, class... U>
  379. struct merge_set_impl<L<T...>, L<U1, U...>>
  380. {
  381. using type = typename merge_set_impl<if_t<contains<L<T...>, U1>,
  382. L<T...>,
  383. L<T..., U1>>,
  384. L<U...>>::type;
  385. };
  386. }
  387. template <class S1, class S2>
  388. struct merge_set : detail::merge_set_impl<S1, S2>
  389. {
  390. };
  391. template <class S1, class S2>
  392. using merge_set_t = typename merge_set<S1, S2>::type;
  393. /***********
  394. * find_if *
  395. ***********/
  396. template <template <class> class Test, class L>
  397. struct find_if;
  398. namespace detail
  399. {
  400. template <template <class> class Test, std::size_t I, class... T>
  401. struct find_if_impl;
  402. template <template <class> class Test, std::size_t I>
  403. struct find_if_impl<Test, I> : size_t_<I>
  404. {
  405. };
  406. template <template <class> class Test, std::size_t I, class T0, class... T>
  407. struct find_if_impl<Test, I, T0, T...> : std::conditional_t<Test<T0>::value,
  408. size_t_<I>,
  409. find_if_impl<Test, I + 1, T...>>
  410. {
  411. };
  412. }
  413. template <template <class> class Test, template <class...> class L, class... T>
  414. struct find_if<Test, L<T...>> : detail::find_if_impl<Test, 0, T...>
  415. {
  416. };
  417. /*********
  418. * split *
  419. *********/
  420. namespace detail
  421. {
  422. template <std::size_t N, class L1, class L2>
  423. struct transfer
  424. {
  425. using new_l1 = push_back_t<L1, front_t<L2>>;
  426. using new_l2 = pop_front_t<L2>;
  427. using new_transfer = transfer<N - 1, new_l1, new_l2>;
  428. using first_type = typename new_transfer::first_type;
  429. using second_type = typename new_transfer::second_type;
  430. };
  431. template <class L1, class L2>
  432. struct transfer<0, L1, L2>
  433. {
  434. using first_type = L1;
  435. using second_type = L2;
  436. };
  437. template <std::size_t N, class L>
  438. struct split_impl
  439. {
  440. using tr_type = transfer<N, vector<>, L>;
  441. using first_type = typename tr_type::first_type;
  442. using second_type = typename tr_type::second_type;
  443. };
  444. }
  445. template <std::size_t N, class L>
  446. struct split : detail::split_impl<N, L>
  447. {
  448. };
  449. /**********
  450. * unique *
  451. **********/
  452. namespace detail
  453. {
  454. template <class L>
  455. struct unique_impl;
  456. template <template <class...> class L, class... T>
  457. struct unique_impl<L<T...>>
  458. {
  459. using type = merge_set_t<L<>, L<T...>>;
  460. };
  461. }
  462. template <class L>
  463. struct unique : detail::unique_impl<L>
  464. {
  465. };
  466. template <class L>
  467. using unique_t = typename unique<L>::type;
  468. /*************
  469. * static_if *
  470. *************/
  471. template <class TF, class FF>
  472. decltype(auto) static_if(std::true_type, const TF& tf, const FF&)
  473. {
  474. return tf(identity());
  475. }
  476. template <class TF, class FF>
  477. decltype(auto) static_if(std::false_type, const TF&, const FF& ff)
  478. {
  479. return ff(identity());
  480. }
  481. template <bool cond, class TF, class FF>
  482. decltype(auto) static_if(const TF& tf, const FF& ff)
  483. {
  484. return static_if(std::integral_constant<bool, cond>(), tf, ff);
  485. }
  486. /***********
  487. * switch_ *
  488. ***********/
  489. using default_t = std::true_type;
  490. namespace detail
  491. {
  492. template <class... T>
  493. struct switch_impl;
  494. template <class C, class T, class... U>
  495. struct switch_impl<C, T, U...>
  496. : std::conditional<C::value, T, typename switch_impl<U...>::type>
  497. {
  498. };
  499. template <class C, class T, class U>
  500. struct switch_impl<C, T, default_t, U>
  501. : std::conditional<C::value, T, U>
  502. {
  503. };
  504. }
  505. template <class... T>
  506. struct switch_ : detail::switch_impl<T...>
  507. {
  508. };
  509. template <class... T>
  510. using switch_t = typename switch_<T...>::type;
  511. }
  512. }
  513. #endif