polyfill_ranges.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  1. // SPDX-FileCopyrightText: 2022 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. //
  4. // TODO: remove this file when ranges are supported by all compilation targets
  5. //
  6. #pragma once
  7. #include <algorithm>
  8. #include <utility>
  9. #include <version>
  10. #ifndef __cpp_lib_ranges
  11. namespace std {
  12. namespace ranges {
  13. template <typename T>
  14. concept range = requires(T& t) {
  15. begin(t);
  16. end(t);
  17. };
  18. template <typename T>
  19. concept input_range = range<T>;
  20. template <typename T>
  21. concept output_range = range<T>;
  22. template <range R>
  23. using range_difference_t = ptrdiff_t;
  24. //
  25. // find, find_if, find_if_not
  26. //
  27. struct find_fn {
  28. template <typename Iterator, typename T, typename Proj = std::identity>
  29. constexpr Iterator operator()(Iterator first, Iterator last, const T& value,
  30. Proj proj = {}) const {
  31. for (; first != last; ++first) {
  32. if (std::invoke(proj, *first) == value) {
  33. return first;
  34. }
  35. }
  36. return first;
  37. }
  38. template <ranges::input_range R, typename T, typename Proj = std::identity>
  39. constexpr ranges::iterator_t<R> operator()(R&& r, const T& value, Proj proj = {}) const {
  40. return operator()(ranges::begin(r), ranges::end(r), value, std::ref(proj));
  41. }
  42. };
  43. struct find_if_fn {
  44. template <typename Iterator, typename Proj = std::identity, typename Pred>
  45. constexpr Iterator operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const {
  46. for (; first != last; ++first) {
  47. if (std::invoke(pred, std::invoke(proj, *first))) {
  48. return first;
  49. }
  50. }
  51. return first;
  52. }
  53. template <ranges::input_range R, typename Proj = std::identity, typename Pred>
  54. constexpr ranges::iterator_t<R> operator()(R&& r, Pred pred, Proj proj = {}) const {
  55. return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
  56. }
  57. };
  58. struct find_if_not_fn {
  59. template <typename Iterator, typename Proj = std::identity, typename Pred>
  60. constexpr Iterator operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const {
  61. for (; first != last; ++first) {
  62. if (!std::invoke(pred, std::invoke(proj, *first))) {
  63. return first;
  64. }
  65. }
  66. return first;
  67. }
  68. template <ranges::input_range R, typename Proj = std::identity, typename Pred>
  69. constexpr ranges::iterator_t<R> operator()(R&& r, Pred pred, Proj proj = {}) const {
  70. return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
  71. }
  72. };
  73. inline constexpr find_fn find;
  74. inline constexpr find_if_fn find_if;
  75. inline constexpr find_if_not_fn find_if_not;
  76. //
  77. // any_of, all_of, none_of
  78. //
  79. struct all_of_fn {
  80. template <typename Iterator, typename Proj = std::identity, typename Pred>
  81. constexpr bool operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const {
  82. return ranges::find_if_not(first, last, std::ref(pred), std::ref(proj)) == last;
  83. }
  84. template <ranges::input_range R, typename Proj = std::identity, typename Pred>
  85. constexpr bool operator()(R&& r, Pred pred, Proj proj = {}) const {
  86. return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
  87. }
  88. };
  89. struct any_of_fn {
  90. template <typename Iterator, typename Proj = std::identity, typename Pred>
  91. constexpr bool operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const {
  92. return ranges::find_if(first, last, std::ref(pred), std::ref(proj)) != last;
  93. }
  94. template <ranges::input_range R, typename Proj = std::identity, typename Pred>
  95. constexpr bool operator()(R&& r, Pred pred, Proj proj = {}) const {
  96. return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
  97. }
  98. };
  99. struct none_of_fn {
  100. template <typename Iterator, typename Proj = std::identity, typename Pred>
  101. constexpr bool operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const {
  102. return ranges::find_if(first, last, std::ref(pred), std::ref(proj)) == last;
  103. }
  104. template <ranges::input_range R, typename Proj = std::identity, typename Pred>
  105. constexpr bool operator()(R&& r, Pred pred, Proj proj = {}) const {
  106. return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
  107. }
  108. };
  109. inline constexpr any_of_fn any_of;
  110. inline constexpr all_of_fn all_of;
  111. inline constexpr none_of_fn none_of;
  112. //
  113. // count, count_if
  114. //
  115. struct count_fn {
  116. template <typename Iterator, typename T, typename Proj = std::identity>
  117. constexpr ptrdiff_t operator()(Iterator first, Iterator last, const T& value,
  118. Proj proj = {}) const {
  119. ptrdiff_t counter = 0;
  120. for (; first != last; ++first)
  121. if (std::invoke(proj, *first) == value)
  122. ++counter;
  123. return counter;
  124. }
  125. template <ranges::input_range R, typename T, typename Proj = std::identity>
  126. constexpr ptrdiff_t operator()(R&& r, const T& value, Proj proj = {}) const {
  127. return operator()(ranges::begin(r), ranges::end(r), value, std::ref(proj));
  128. }
  129. };
  130. struct count_if_fn {
  131. template <typename Iterator, typename Proj = std::identity, typename Pred>
  132. constexpr ptrdiff_t operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const {
  133. ptrdiff_t counter = 0;
  134. for (; first != last; ++first)
  135. if (std::invoke(pred, std::invoke(proj, *first)))
  136. ++counter;
  137. return counter;
  138. }
  139. template <ranges::input_range R, typename Proj = std::identity, typename Pred>
  140. constexpr ptrdiff_t operator()(R&& r, Pred pred, Proj proj = {}) const {
  141. return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
  142. }
  143. };
  144. inline constexpr count_fn count;
  145. inline constexpr count_if_fn count_if;
  146. //
  147. // transform
  148. //
  149. struct transform_fn {
  150. template <typename InputIterator, typename OutputIterator, typename F,
  151. typename Proj = std::identity>
  152. constexpr void operator()(InputIterator first1, InputIterator last1, OutputIterator result,
  153. F op, Proj proj = {}) const {
  154. for (; first1 != last1; ++first1, (void)++result) {
  155. *result = std::invoke(op, std::invoke(proj, *first1));
  156. }
  157. }
  158. template <ranges::input_range R, typename OutputIterator, typename F,
  159. typename Proj = std::identity>
  160. constexpr void operator()(R&& r, OutputIterator result, F op, Proj proj = {}) const {
  161. return operator()(ranges::begin(r), ranges::end(r), result, std::ref(op), std::ref(proj));
  162. }
  163. };
  164. inline constexpr transform_fn transform;
  165. //
  166. // sort
  167. //
  168. struct sort_fn {
  169. template <typename Iterator, typename Comp = ranges::less, typename Proj = std::identity>
  170. constexpr void operator()(Iterator first, Iterator last, Comp comp = {}, Proj proj = {}) const {
  171. if (first == last)
  172. return;
  173. Iterator last_iter = ranges::next(first, last);
  174. std::sort(first, last_iter,
  175. [&](auto& lhs, auto& rhs) { return comp(proj(lhs), proj(rhs)); });
  176. }
  177. template <ranges::input_range R, typename Comp = ranges::less, typename Proj = std::identity>
  178. constexpr void operator()(R&& r, Comp comp = {}, Proj proj = {}) const {
  179. return operator()(ranges::begin(r), ranges::end(r), std::move(comp), std::move(proj));
  180. }
  181. };
  182. inline constexpr sort_fn sort;
  183. //
  184. // fill
  185. //
  186. struct fill_fn {
  187. template <typename T, typename OutputIterator>
  188. constexpr OutputIterator operator()(OutputIterator first, OutputIterator last,
  189. const T& value) const {
  190. while (first != last) {
  191. *first++ = value;
  192. }
  193. return first;
  194. }
  195. template <typename T, ranges::output_range R>
  196. constexpr ranges::iterator_t<R> operator()(R&& r, const T& value) const {
  197. return operator()(ranges::begin(r), ranges::end(r), value);
  198. }
  199. };
  200. inline constexpr fill_fn fill;
  201. //
  202. // for_each
  203. //
  204. struct for_each_fn {
  205. template <typename Iterator, typename Proj = std::identity, typename Fun>
  206. constexpr void operator()(Iterator first, Iterator last, Fun f, Proj proj = {}) const {
  207. for (; first != last; ++first) {
  208. std::invoke(f, std::invoke(proj, *first));
  209. }
  210. }
  211. template <ranges::input_range R, typename Proj = std::identity, typename Fun>
  212. constexpr void operator()(R&& r, Fun f, Proj proj = {}) const {
  213. return operator()(ranges::begin(r), ranges::end(r), std::move(f), std::ref(proj));
  214. }
  215. };
  216. inline constexpr for_each_fn for_each;
  217. //
  218. // min_element, max_element
  219. //
  220. struct min_element_fn {
  221. template <typename Iterator, typename Proj = std::identity, typename Comp = ranges::less>
  222. constexpr Iterator operator()(Iterator first, Iterator last, Comp comp = {},
  223. Proj proj = {}) const {
  224. if (first == last) {
  225. return last;
  226. }
  227. auto smallest = first;
  228. ++first;
  229. for (; first != last; ++first) {
  230. if (!std::invoke(comp, std::invoke(proj, *smallest), std::invoke(proj, *first))) {
  231. smallest = first;
  232. }
  233. }
  234. return smallest;
  235. }
  236. template <ranges::input_range R, typename Proj = std::identity, typename Comp = ranges::less>
  237. constexpr ranges::iterator_t<R> operator()(R&& r, Comp comp = {}, Proj proj = {}) const {
  238. return operator()(ranges::begin(r), ranges::end(r), std::ref(comp), std::ref(proj));
  239. }
  240. };
  241. struct max_element_fn {
  242. template <typename Iterator, typename Proj = std::identity, typename Comp = ranges::less>
  243. constexpr Iterator operator()(Iterator first, Iterator last, Comp comp = {},
  244. Proj proj = {}) const {
  245. if (first == last) {
  246. return last;
  247. }
  248. auto largest = first;
  249. ++first;
  250. for (; first != last; ++first) {
  251. if (std::invoke(comp, std::invoke(proj, *largest), std::invoke(proj, *first))) {
  252. largest = first;
  253. }
  254. }
  255. return largest;
  256. }
  257. template <ranges::input_range R, typename Proj = std::identity, typename Comp = ranges::less>
  258. constexpr ranges::iterator_t<R> operator()(R&& r, Comp comp = {}, Proj proj = {}) const {
  259. return operator()(ranges::begin(r), ranges::end(r), std::ref(comp), std::ref(proj));
  260. }
  261. };
  262. inline constexpr min_element_fn min_element;
  263. inline constexpr max_element_fn max_element;
  264. //
  265. // replace, replace_if
  266. //
  267. struct replace_fn {
  268. template <typename Iterator, typename T1, typename T2, typename Proj = std::identity>
  269. constexpr Iterator operator()(Iterator first, Iterator last, const T1& old_value,
  270. const T2& new_value, Proj proj = {}) const {
  271. for (; first != last; ++first) {
  272. if (old_value == std::invoke(proj, *first)) {
  273. *first = new_value;
  274. }
  275. }
  276. return first;
  277. }
  278. template <ranges::input_range R, typename T1, typename T2, typename Proj = std::identity>
  279. constexpr ranges::iterator_t<R> operator()(R&& r, const T1& old_value, const T2& new_value,
  280. Proj proj = {}) const {
  281. return operator()(ranges::begin(r), ranges::end(r), old_value, new_value, std::move(proj));
  282. }
  283. };
  284. struct replace_if_fn {
  285. template <typename Iterator, typename T, typename Proj = std::identity, typename Pred>
  286. constexpr Iterator operator()(Iterator first, Iterator last, Pred pred, const T& new_value,
  287. Proj proj = {}) const {
  288. for (; first != last; ++first) {
  289. if (!!std::invoke(pred, std::invoke(proj, *first))) {
  290. *first = new_value;
  291. }
  292. }
  293. return std::move(first);
  294. }
  295. template <ranges::input_range R, typename T, typename Proj = std::identity, typename Pred>
  296. constexpr ranges::iterator_t<R> operator()(R&& r, Pred pred, const T& new_value,
  297. Proj proj = {}) const {
  298. return operator()(ranges::begin(r), ranges::end(r), std::move(pred), new_value,
  299. std::move(proj));
  300. }
  301. };
  302. inline constexpr replace_fn replace;
  303. inline constexpr replace_if_fn replace_if;
  304. //
  305. // copy, copy_if
  306. //
  307. struct copy_fn {
  308. template <typename InputIterator, typename OutputIterator>
  309. constexpr void operator()(InputIterator first, InputIterator last,
  310. OutputIterator result) const {
  311. for (; first != last; ++first, (void)++result) {
  312. *result = *first;
  313. }
  314. }
  315. template <ranges::input_range R, typename OutputIterator>
  316. constexpr void operator()(R&& r, OutputIterator result) const {
  317. return operator()(ranges::begin(r), ranges::end(r), std::move(result));
  318. }
  319. };
  320. struct copy_if_fn {
  321. template <typename InputIterator, typename OutputIterator, typename Proj = std::identity,
  322. typename Pred>
  323. constexpr void operator()(InputIterator first, InputIterator last, OutputIterator result,
  324. Pred pred, Proj proj = {}) const {
  325. for (; first != last; ++first) {
  326. if (std::invoke(pred, std::invoke(proj, *first))) {
  327. *result = *first;
  328. ++result;
  329. }
  330. }
  331. }
  332. template <ranges::input_range R, typename OutputIterator, typename Proj = std::identity,
  333. typename Pred>
  334. constexpr void operator()(R&& r, OutputIterator result, Pred pred, Proj proj = {}) const {
  335. return operator()(ranges::begin(r), ranges::end(r), std::move(result), std::ref(pred),
  336. std::ref(proj));
  337. }
  338. };
  339. inline constexpr copy_fn copy;
  340. inline constexpr copy_if_fn copy_if;
  341. //
  342. // generate
  343. //
  344. struct generate_fn {
  345. template <typename Iterator, typename F>
  346. constexpr Iterator operator()(Iterator first, Iterator last, F gen) const {
  347. for (; first != last; *first = std::invoke(gen), ++first)
  348. ;
  349. return first;
  350. }
  351. template <typename R, std::copy_constructible F>
  352. requires std::invocable<F&> && ranges::output_range<R>
  353. constexpr ranges::iterator_t<R> operator()(R&& r, F gen) const {
  354. return operator()(ranges::begin(r), ranges::end(r), std::move(gen));
  355. }
  356. };
  357. inline constexpr generate_fn generate;
  358. //
  359. // lower_bound, upper_bound
  360. //
  361. struct lower_bound_fn {
  362. template <typename Iterator, typename T, typename Proj = std::identity,
  363. typename Comp = ranges::less>
  364. constexpr Iterator operator()(Iterator first, Iterator last, const T& value, Comp comp = {},
  365. Proj proj = {}) const {
  366. Iterator it;
  367. std::ptrdiff_t _count, _step;
  368. _count = std::distance(first, last);
  369. while (_count > 0) {
  370. it = first;
  371. _step = _count / 2;
  372. ranges::advance(it, _step, last);
  373. if (comp(std::invoke(proj, *it), value)) {
  374. first = ++it;
  375. _count -= _step + 1;
  376. } else {
  377. _count = _step;
  378. }
  379. }
  380. return first;
  381. }
  382. template <ranges::input_range R, typename T, typename Proj = std::identity,
  383. typename Comp = ranges::less>
  384. constexpr ranges::iterator_t<R> operator()(R&& r, const T& value, Comp comp = {},
  385. Proj proj = {}) const {
  386. return operator()(ranges::begin(r), ranges::end(r), value, std::ref(comp), std::ref(proj));
  387. }
  388. };
  389. struct upper_bound_fn {
  390. template <typename Iterator, typename T, typename Proj = std::identity,
  391. typename Comp = ranges::less>
  392. constexpr Iterator operator()(Iterator first, Iterator last, const T& value, Comp comp = {},
  393. Proj proj = {}) const {
  394. Iterator it;
  395. std::ptrdiff_t _count, _step;
  396. _count = std::distance(first, last);
  397. while (_count > 0) {
  398. it = first;
  399. _step = _count / 2;
  400. ranges::advance(it, _step, last);
  401. if (!comp(value, std::invoke(proj, *it))) {
  402. first = ++it;
  403. _count -= _step + 1;
  404. } else {
  405. _count = _step;
  406. }
  407. }
  408. return first;
  409. }
  410. template <ranges::input_range R, typename T, typename Proj = std::identity,
  411. typename Comp = ranges::less>
  412. constexpr ranges::iterator_t<R> operator()(R&& r, const T& value, Comp comp = {},
  413. Proj proj = {}) const {
  414. return operator()(ranges::begin(r), ranges::end(r), value, std::ref(comp), std::ref(proj));
  415. }
  416. };
  417. inline constexpr lower_bound_fn lower_bound;
  418. inline constexpr upper_bound_fn upper_bound;
  419. //
  420. // adjacent_find
  421. //
  422. struct adjacent_find_fn {
  423. template <typename Iterator, typename Proj = std::identity, typename Pred = ranges::equal_to>
  424. constexpr Iterator operator()(Iterator first, Iterator last, Pred pred = {},
  425. Proj proj = {}) const {
  426. if (first == last)
  427. return first;
  428. auto _next = ranges::next(first);
  429. for (; _next != last; ++_next, ++first)
  430. if (std::invoke(pred, std::invoke(proj, *first), std::invoke(proj, *_next)))
  431. return first;
  432. return _next;
  433. }
  434. template <ranges::input_range R, typename Proj = std::identity,
  435. typename Pred = ranges::equal_to>
  436. constexpr ranges::iterator_t<R> operator()(R&& r, Pred pred = {}, Proj proj = {}) const {
  437. return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
  438. }
  439. };
  440. inline constexpr adjacent_find_fn adjacent_find;
  441. } // namespace ranges
  442. } // namespace std
  443. #endif