mappers.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. // This file is part of Desktop App Toolkit,
  2. // a set of libraries for developing nice desktop applications.
  3. //
  4. // For license and copyright information please follow this link:
  5. // https://github.com/desktop-app/legal/blob/master/LEGAL
  6. //
  7. #pragma once
  8. namespace rpl {
  9. namespace details {
  10. struct base_mapper {
  11. };
  12. template <typename Type>
  13. constexpr bool is_mapper_v = std::is_base_of_v<
  14. base_mapper,
  15. std::decay_t<Type>>;
  16. template <std::size_t Index>
  17. struct argument_mapper : base_mapper {
  18. template <
  19. typename Arg,
  20. typename ...Args,
  21. typename = std::enable_if_t<(sizeof...(Args) >= Index)>>
  22. static constexpr decltype(auto) call(Arg &&arg, Args &&...args) {
  23. return argument_mapper<Index - 1>::call(
  24. std::forward<Args>(args)...);
  25. }
  26. template <
  27. typename ...Args,
  28. typename = std::enable_if_t<(sizeof...(Args) > Index)>>
  29. constexpr auto operator()(Args &&...args) const {
  30. return call(std::forward<Args>(args)...);
  31. }
  32. };
  33. template <>
  34. struct argument_mapper<0> : base_mapper {
  35. template <
  36. typename Arg,
  37. typename ...Args>
  38. static constexpr decltype(auto) call(Arg &&arg, Args &&...args) {
  39. return std::forward<Arg>(arg);
  40. }
  41. template <
  42. typename Arg,
  43. typename ...Args>
  44. constexpr auto operator()(Arg &&arg, Args &&...args) const {
  45. return std::forward<Arg>(arg);
  46. }
  47. };
  48. template <typename Type>
  49. class value_mapper : public base_mapper {
  50. public:
  51. template <typename OtherType>
  52. constexpr value_mapper(OtherType &&value)
  53. : _value(std::forward<OtherType>(value)) {
  54. }
  55. template <typename ...Args>
  56. constexpr auto operator()(Args &&...args) const {
  57. return _value;
  58. }
  59. private:
  60. Type _value;
  61. };
  62. template <typename Type>
  63. struct wrap_mapper {
  64. using type = std::conditional_t<
  65. is_mapper_v<Type>,
  66. Type,
  67. value_mapper<Type>>;
  68. };
  69. template <typename Type>
  70. using wrap_mapper_t = typename wrap_mapper<Type>::type;
  71. template <typename Type, typename Operator>
  72. class unary_operator_mapper : public base_mapper {
  73. using TypeWrapper = wrap_mapper_t<std::decay_t<Type>>;
  74. public:
  75. template <typename OtherType>
  76. constexpr unary_operator_mapper(OtherType &&value)
  77. : _value(std::forward<OtherType>(value)) {
  78. }
  79. template <
  80. typename ...Args,
  81. typename Result = decltype((Operator{})(
  82. std::declval<TypeWrapper>()(std::declval<Args>()...)))>
  83. constexpr std::decay_t<Result> operator()(Args &&...args) const {
  84. return (Operator{})(
  85. _value(std::forward<Args>(args)...));
  86. }
  87. private:
  88. TypeWrapper _value;
  89. };
  90. template <typename Left, typename Right, typename Operator>
  91. class binary_operator_mapper : public base_mapper {
  92. using LeftWrapper = wrap_mapper_t<std::decay_t<Left>>;
  93. using RightWrapper = wrap_mapper_t<std::decay_t<Right>>;
  94. public:
  95. template <typename OtherLeft, typename OtherRight>
  96. constexpr binary_operator_mapper(OtherLeft &&left, OtherRight &&right)
  97. : _left(std::forward<OtherLeft>(left))
  98. , _right(std::forward<OtherRight>(right)) {
  99. }
  100. template <
  101. typename ...Args,
  102. typename Result = decltype((Operator{})(
  103. std::declval<LeftWrapper>()(std::declval<Args>()...),
  104. std::declval<RightWrapper>()(std::declval<Args>()...)))>
  105. constexpr std::decay_t<Result> operator()(Args &&...args) const {
  106. return (Operator{})(
  107. _left(std::forward<Args>(args)...),
  108. _right(std::forward<Args>(args)...));
  109. }
  110. private:
  111. LeftWrapper _left;
  112. RightWrapper _right;
  113. };
  114. template <
  115. typename Left,
  116. typename Right,
  117. typename = std::enable_if_t<
  118. is_mapper_v<Left> || is_mapper_v<Right>
  119. >>
  120. inline auto operator+(Left &&left, Right &&right) {
  121. return binary_operator_mapper<
  122. Left,
  123. Right,
  124. std::plus<>>(
  125. std::forward<Left>(left),
  126. std::forward<Right>(right));
  127. }
  128. template <
  129. typename Left,
  130. typename Right,
  131. typename = std::enable_if_t<
  132. is_mapper_v<Left> || is_mapper_v<Right>
  133. >>
  134. inline auto operator-(Left &&left, Right &&right) {
  135. return binary_operator_mapper<
  136. Left,
  137. Right,
  138. std::minus<>>(
  139. std::forward<Left>(left),
  140. std::forward<Right>(right));
  141. }
  142. template <
  143. typename Left,
  144. typename Right,
  145. typename = std::enable_if_t<
  146. is_mapper_v<Left> || is_mapper_v<Right>
  147. >>
  148. inline auto operator*(Left &&left, Right &&right) {
  149. return binary_operator_mapper<
  150. Left,
  151. Right,
  152. std::multiplies<>>(
  153. std::forward<Left>(left),
  154. std::forward<Right>(right));
  155. }
  156. template <
  157. typename Left,
  158. typename Right,
  159. typename = std::enable_if_t<
  160. is_mapper_v<Left> || is_mapper_v<Right>
  161. >>
  162. inline auto operator/(Left &&left, Right &&right) {
  163. return binary_operator_mapper<
  164. Left,
  165. Right,
  166. std::divides<>>(
  167. std::forward<Left>(left),
  168. std::forward<Right>(right));
  169. }
  170. template <
  171. typename Left,
  172. typename Right,
  173. typename = std::enable_if_t<
  174. is_mapper_v<Left> || is_mapper_v<Right>
  175. >>
  176. inline auto operator%(Left &&left, Right &&right) {
  177. return binary_operator_mapper<
  178. Left,
  179. Right,
  180. std::modulus<>>(
  181. std::forward<Left>(left),
  182. std::forward<Right>(right));
  183. }
  184. template <
  185. typename Type,
  186. typename = std::enable_if_t<
  187. is_mapper_v<Type>
  188. >>
  189. inline auto operator-(Type &&value) {
  190. return unary_operator_mapper<
  191. Type,
  192. std::negate<>>(
  193. std::forward<Type>(value));
  194. }
  195. template <
  196. typename Left,
  197. typename Right,
  198. typename = std::enable_if_t<
  199. is_mapper_v<Left> || is_mapper_v<Right>
  200. >>
  201. inline auto operator<(Left &&left, Right &&right) {
  202. return binary_operator_mapper<
  203. Left,
  204. Right,
  205. std::less<>>(
  206. std::forward<Left>(left),
  207. std::forward<Right>(right));
  208. }
  209. template <
  210. typename Left,
  211. typename Right,
  212. typename = std::enable_if_t<
  213. is_mapper_v<Left> || is_mapper_v<Right>
  214. >>
  215. inline auto operator<=(Left &&left, Right &&right) {
  216. return binary_operator_mapper<
  217. Left,
  218. Right,
  219. std::less_equal<>>(
  220. std::forward<Left>(left),
  221. std::forward<Right>(right));
  222. }
  223. template <
  224. typename Left,
  225. typename Right,
  226. typename = std::enable_if_t<
  227. is_mapper_v<Left> || is_mapper_v<Right>
  228. >>
  229. inline auto operator>(Left &&left, Right &&right) {
  230. return binary_operator_mapper<
  231. Left,
  232. Right,
  233. std::greater<>>(
  234. std::forward<Left>(left),
  235. std::forward<Right>(right));
  236. }
  237. template <
  238. typename Left,
  239. typename Right,
  240. typename = std::enable_if_t<
  241. is_mapper_v<Left> || is_mapper_v<Right>
  242. >>
  243. inline auto operator>=(Left &&left, Right &&right) {
  244. return binary_operator_mapper<
  245. Left,
  246. Right,
  247. std::greater_equal<>>(
  248. std::forward<Left>(left),
  249. std::forward<Right>(right));
  250. }
  251. template <
  252. typename Left,
  253. typename Right,
  254. typename = std::enable_if_t<
  255. is_mapper_v<Left> || is_mapper_v<Right>
  256. >>
  257. inline auto operator==(Left &&left, Right &&right) {
  258. return binary_operator_mapper<
  259. Left,
  260. Right,
  261. std::equal_to<>>(
  262. std::forward<Left>(left),
  263. std::forward<Right>(right));
  264. }
  265. template <
  266. typename Left,
  267. typename Right,
  268. typename = std::enable_if_t<
  269. is_mapper_v<Left> || is_mapper_v<Right>
  270. >>
  271. inline auto operator!=(Left &&left, Right &&right) {
  272. return binary_operator_mapper<
  273. Left,
  274. Right,
  275. std::not_equal_to<>>(
  276. std::forward<Left>(left),
  277. std::forward<Right>(right));
  278. }
  279. template <
  280. typename Left,
  281. typename Right,
  282. typename = std::enable_if_t<
  283. is_mapper_v<Left> || is_mapper_v<Right>
  284. >>
  285. inline auto operator&&(Left &&left, Right &&right) {
  286. return binary_operator_mapper<
  287. Left,
  288. Right,
  289. std::logical_and<>>(
  290. std::forward<Left>(left),
  291. std::forward<Right>(right));
  292. }
  293. template <
  294. typename Left,
  295. typename Right,
  296. typename = std::enable_if_t<
  297. is_mapper_v<Left> || is_mapper_v<Right>
  298. >>
  299. inline auto operator||(Left &&left, Right &&right) {
  300. return binary_operator_mapper<
  301. Left,
  302. Right,
  303. std::logical_or<>>(
  304. std::forward<Left>(left),
  305. std::forward<Right>(right));
  306. }
  307. template <
  308. typename Type,
  309. typename = std::enable_if_t<
  310. is_mapper_v<Type>
  311. >>
  312. inline auto operator!(Type &&value) {
  313. return unary_operator_mapper<
  314. Type,
  315. std::logical_not<>>(
  316. std::forward<Type>(value));
  317. }
  318. template <
  319. typename Left,
  320. typename Right,
  321. typename = std::enable_if_t<
  322. is_mapper_v<Left> || is_mapper_v<Right>
  323. >>
  324. inline auto operator&(Left &&left, Right &&right) {
  325. return binary_operator_mapper<
  326. Left,
  327. Right,
  328. std::bit_and<>>(
  329. std::forward<Left>(left),
  330. std::forward<Right>(right));
  331. }
  332. template <
  333. typename Left,
  334. typename Right,
  335. typename = std::enable_if_t<
  336. is_mapper_v<Left> || is_mapper_v<Right>
  337. >>
  338. inline auto operator|(Left &&left, Right &&right) {
  339. return binary_operator_mapper<
  340. Left,
  341. Right,
  342. std::bit_or<>>(
  343. std::forward<Left>(left),
  344. std::forward<Right>(right));
  345. }
  346. template <
  347. typename Left,
  348. typename Right,
  349. typename = std::enable_if_t<
  350. is_mapper_v<Left> || is_mapper_v<Right>
  351. >>
  352. inline auto operator^(Left &&left, Right &&right) {
  353. return binary_operator_mapper<
  354. Left,
  355. Right,
  356. std::bit_xor<>>(
  357. std::forward<Left>(left),
  358. std::forward<Right>(right));
  359. }
  360. template <
  361. typename Type,
  362. typename = std::enable_if_t<
  363. is_mapper_v<Type>
  364. >>
  365. inline auto operator~(Type &&value) {
  366. return unary_operator_mapper<
  367. Type,
  368. std::bit_not<>>(
  369. std::forward<Type>(value));
  370. }
  371. template <typename ...Mappers>
  372. class tuple_mapper {
  373. template <typename ...Args>
  374. using tuple_result = std::tuple<decltype(
  375. std::declval<wrap_mapper_t<std::decay_t<Mappers>>>()(
  376. std::declval<Args>()...))...>;
  377. public:
  378. template <typename ...OtherMappers>
  379. tuple_mapper(OtherMappers &&...mappers) : _mappers(
  380. std::forward<OtherMappers>(mappers)...) {
  381. }
  382. template <typename ...Args>
  383. constexpr tuple_result<Args...> operator()(
  384. Args &&...args) const {
  385. constexpr auto kArity = sizeof...(Mappers);
  386. return call_helper(
  387. std::make_index_sequence<kArity>(),
  388. std::forward<Args>(args)...);
  389. }
  390. private:
  391. template <typename ...Args, std::size_t ...I>
  392. inline tuple_result<Args...> call_helper(
  393. std::index_sequence<I...>,
  394. Args &&...args) const {
  395. return std::make_tuple(
  396. std::get<I>(_mappers)(std::forward<Args>(args)...)...);
  397. }
  398. std::tuple<wrap_mapper_t<std::decay_t<Mappers>>...> _mappers;
  399. };
  400. template <typename ...Args>
  401. tuple_mapper<Args...> tuple(Args &&...args) {
  402. return tuple_mapper<Args...>(std::forward<Args>(args)...);
  403. }
  404. } // namespace details
  405. namespace mappers {
  406. constexpr const details::argument_mapper<0> _1;
  407. constexpr const details::argument_mapper<1> _2;
  408. constexpr const details::argument_mapper<2> _3;
  409. constexpr const details::argument_mapper<3> _4;
  410. constexpr const details::argument_mapper<4> _5;
  411. constexpr const details::argument_mapper<5> _6;
  412. constexpr const details::argument_mapper<6> _7;
  413. constexpr const details::argument_mapper<7> _8;
  414. constexpr const details::argument_mapper<8> _9;
  415. constexpr const details::argument_mapper<9> _10;
  416. constexpr const auto _1_of_two = ((void)_2, _1);
  417. } // namespace mappers
  418. } // namespace rpl