xref: /llvm-project/libcxx/include/__algorithm/ranges_merge.h (revision d10dc5a06fac4dcabf2264c64c8672c6f6ae36fb)
125607d14SHui Xie //===----------------------------------------------------------------------===//
225607d14SHui Xie //
325607d14SHui Xie // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
425607d14SHui Xie // See https://llvm.org/LICENSE.txt for license information.
525607d14SHui Xie // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
625607d14SHui Xie //
725607d14SHui Xie //===----------------------------------------------------------------------===//
825607d14SHui Xie 
925607d14SHui Xie #ifndef _LIBCPP___ALGORITHM_RANGES_MERGE_H
1025607d14SHui Xie #define _LIBCPP___ALGORITHM_RANGES_MERGE_H
1125607d14SHui Xie 
1225607d14SHui Xie #include <__algorithm/in_in_out_result.h>
1325607d14SHui Xie #include <__algorithm/ranges_copy.h>
1425607d14SHui Xie #include <__config>
1525607d14SHui Xie #include <__functional/identity.h>
1625607d14SHui Xie #include <__functional/invoke.h>
1725607d14SHui Xie #include <__functional/ranges_operations.h>
1825607d14SHui Xie #include <__iterator/concepts.h>
1925607d14SHui Xie #include <__iterator/mergeable.h>
2025607d14SHui Xie #include <__ranges/access.h>
2125607d14SHui Xie #include <__ranges/concepts.h>
2225607d14SHui Xie #include <__ranges/dangling.h>
23e698c595SNikolas Klauser #include <__type_traits/remove_cvref.h>
2425607d14SHui Xie #include <__utility/move.h>
2525607d14SHui Xie 
2625607d14SHui Xie #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
2725607d14SHui Xie #  pragma GCC system_header
2825607d14SHui Xie #endif
2925607d14SHui Xie 
307b462251SLouis Dionne _LIBCPP_PUSH_MACROS
317b462251SLouis Dionne #include <__undef_macros>
327b462251SLouis Dionne 
334f15267dSNikolas Klauser #if _LIBCPP_STD_VER >= 20
3425607d14SHui Xie 
3525607d14SHui Xie _LIBCPP_BEGIN_NAMESPACE_STD
3625607d14SHui Xie 
3725607d14SHui Xie namespace ranges {
3825607d14SHui Xie 
3925607d14SHui Xie template <class _InIter1, class _InIter2, class _OutIter>
4025607d14SHui Xie using merge_result = in_in_out_result<_InIter1, _InIter2, _OutIter>;
4125607d14SHui Xie 
42*d10dc5a0SChristopher Di Bella struct __merge {
435aa03b64SLouis Dionne   template <input_iterator _InIter1,
4425607d14SHui Xie             sentinel_for<_InIter1> _Sent1,
4525607d14SHui Xie             input_iterator _InIter2,
4625607d14SHui Xie             sentinel_for<_InIter2> _Sent2,
4725607d14SHui Xie             weakly_incrementable _OutIter,
4825607d14SHui Xie             class _Comp  = less,
4925607d14SHui Xie             class _Proj1 = identity,
5025607d14SHui Xie             class _Proj2 = identity>
5125607d14SHui Xie     requires mergeable<_InIter1, _InIter2, _OutIter, _Comp, _Proj1, _Proj2>
5225607d14SHui Xie   _LIBCPP_HIDE_FROM_ABI constexpr merge_result<_InIter1, _InIter2, _OutIter> operator()(
5325607d14SHui Xie       _InIter1 __first1,
5425607d14SHui Xie       _Sent1 __last1,
5525607d14SHui Xie       _InIter2 __first2,
5625607d14SHui Xie       _Sent2 __last2,
5725607d14SHui Xie       _OutIter __result,
5825607d14SHui Xie       _Comp __comp   = {},
5925607d14SHui Xie       _Proj1 __proj1 = {},
6025607d14SHui Xie       _Proj2 __proj2 = {}) const {
6125607d14SHui Xie     return __merge::__merge_impl(__first1, __last1, __first2, __last2, __result, __comp, __proj1, __proj2);
6225607d14SHui Xie   }
6325607d14SHui Xie 
645aa03b64SLouis Dionne   template <input_range _Range1,
6525607d14SHui Xie             input_range _Range2,
6625607d14SHui Xie             weakly_incrementable _OutIter,
6725607d14SHui Xie             class _Comp  = less,
6825607d14SHui Xie             class _Proj1 = identity,
6925607d14SHui Xie             class _Proj2 = identity>
705aa03b64SLouis Dionne     requires mergeable<iterator_t<_Range1>, iterator_t<_Range2>, _OutIter, _Comp, _Proj1, _Proj2>
7125607d14SHui Xie   _LIBCPP_HIDE_FROM_ABI constexpr merge_result<borrowed_iterator_t<_Range1>, borrowed_iterator_t<_Range2>, _OutIter>
725aa03b64SLouis Dionne   operator()(_Range1&& __range1,
7325607d14SHui Xie              _Range2&& __range2,
7425607d14SHui Xie              _OutIter __result,
7525607d14SHui Xie              _Comp __comp   = {},
7625607d14SHui Xie              _Proj1 __proj1 = {},
7725607d14SHui Xie              _Proj2 __proj2 = {}) const {
7825607d14SHui Xie     return __merge::__merge_impl(
7925607d14SHui Xie         ranges::begin(__range1),
8025607d14SHui Xie         ranges::end(__range1),
8125607d14SHui Xie         ranges::begin(__range2),
8225607d14SHui Xie         ranges::end(__range2),
8325607d14SHui Xie         __result,
8425607d14SHui Xie         __comp,
8525607d14SHui Xie         __proj1,
8625607d14SHui Xie         __proj2);
8725607d14SHui Xie   }
88*d10dc5a0SChristopher Di Bella 
89*d10dc5a0SChristopher Di Bella   template < class _InIter1,
90*d10dc5a0SChristopher Di Bella              class _Sent1,
91*d10dc5a0SChristopher Di Bella              class _InIter2,
92*d10dc5a0SChristopher Di Bella              class _Sent2,
93*d10dc5a0SChristopher Di Bella              class _OutIter,
94*d10dc5a0SChristopher Di Bella              class _Comp,
95*d10dc5a0SChristopher Di Bella              class _Proj1,
96*d10dc5a0SChristopher Di Bella              class _Proj2>
97*d10dc5a0SChristopher Di Bella   _LIBCPP_HIDE_FROM_ABI static constexpr merge_result<__remove_cvref_t<_InIter1>,
98*d10dc5a0SChristopher Di Bella                                                       __remove_cvref_t<_InIter2>,
99*d10dc5a0SChristopher Di Bella                                                       __remove_cvref_t<_OutIter>>
100*d10dc5a0SChristopher Di Bella   __merge_impl(_InIter1&& __first1,
101*d10dc5a0SChristopher Di Bella                _Sent1&& __last1,
102*d10dc5a0SChristopher Di Bella                _InIter2&& __first2,
103*d10dc5a0SChristopher Di Bella                _Sent2&& __last2,
104*d10dc5a0SChristopher Di Bella                _OutIter&& __result,
105*d10dc5a0SChristopher Di Bella                _Comp&& __comp,
106*d10dc5a0SChristopher Di Bella                _Proj1&& __proj1,
107*d10dc5a0SChristopher Di Bella                _Proj2&& __proj2) {
108*d10dc5a0SChristopher Di Bella     for (; __first1 != __last1 && __first2 != __last2; ++__result) {
109*d10dc5a0SChristopher Di Bella       if (std::invoke(__comp, std::invoke(__proj2, *__first2), std::invoke(__proj1, *__first1))) {
110*d10dc5a0SChristopher Di Bella         *__result = *__first2;
111*d10dc5a0SChristopher Di Bella         ++__first2;
112*d10dc5a0SChristopher Di Bella       } else {
113*d10dc5a0SChristopher Di Bella         *__result = *__first1;
114*d10dc5a0SChristopher Di Bella         ++__first1;
115*d10dc5a0SChristopher Di Bella       }
116*d10dc5a0SChristopher Di Bella     }
117*d10dc5a0SChristopher Di Bella     auto __ret1 = ranges::copy(std::move(__first1), std::move(__last1), std::move(__result));
118*d10dc5a0SChristopher Di Bella     auto __ret2 = ranges::copy(std::move(__first2), std::move(__last2), std::move(__ret1.out));
119*d10dc5a0SChristopher Di Bella     return {std::move(__ret1.in), std::move(__ret2.in), std::move(__ret2.out)};
120*d10dc5a0SChristopher Di Bella   }
12125607d14SHui Xie };
12225607d14SHui Xie 
12325607d14SHui Xie inline namespace __cpo {
124*d10dc5a0SChristopher Di Bella inline constexpr auto merge = __merge{};
12525607d14SHui Xie } // namespace __cpo
12625607d14SHui Xie } // namespace ranges
12725607d14SHui Xie 
12825607d14SHui Xie _LIBCPP_END_NAMESPACE_STD
12925607d14SHui Xie 
1304f15267dSNikolas Klauser #endif // _LIBCPP_STD_VER >= 20
13125607d14SHui Xie 
1327b462251SLouis Dionne _LIBCPP_POP_MACROS
1337b462251SLouis Dionne 
13425607d14SHui Xie #endif // _LIBCPP___ALGORITHM_RANGES_MERGE_H
135