1*4bdff4beSrobert //===----------------------------------------------------------------------===//
2*4bdff4beSrobert //
3*4bdff4beSrobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*4bdff4beSrobert // See https://llvm.org/LICENSE.txt for license information.
5*4bdff4beSrobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*4bdff4beSrobert //
7*4bdff4beSrobert //===----------------------------------------------------------------------===//
8*4bdff4beSrobert 
9*4bdff4beSrobert #ifndef _LIBCPP___ALGORITHM_RANGES_MERGE_H
10*4bdff4beSrobert #define _LIBCPP___ALGORITHM_RANGES_MERGE_H
11*4bdff4beSrobert 
12*4bdff4beSrobert #include <__algorithm/in_in_out_result.h>
13*4bdff4beSrobert #include <__algorithm/ranges_copy.h>
14*4bdff4beSrobert #include <__config>
15*4bdff4beSrobert #include <__functional/identity.h>
16*4bdff4beSrobert #include <__functional/invoke.h>
17*4bdff4beSrobert #include <__functional/ranges_operations.h>
18*4bdff4beSrobert #include <__iterator/concepts.h>
19*4bdff4beSrobert #include <__iterator/mergeable.h>
20*4bdff4beSrobert #include <__ranges/access.h>
21*4bdff4beSrobert #include <__ranges/concepts.h>
22*4bdff4beSrobert #include <__ranges/dangling.h>
23*4bdff4beSrobert #include <__utility/move.h>
24*4bdff4beSrobert #include <type_traits>
25*4bdff4beSrobert 
26*4bdff4beSrobert #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
27*4bdff4beSrobert #  pragma GCC system_header
28*4bdff4beSrobert #endif
29*4bdff4beSrobert 
30*4bdff4beSrobert #if _LIBCPP_STD_VER > 17
31*4bdff4beSrobert 
32*4bdff4beSrobert _LIBCPP_BEGIN_NAMESPACE_STD
33*4bdff4beSrobert 
34*4bdff4beSrobert namespace ranges {
35*4bdff4beSrobert 
36*4bdff4beSrobert template <class _InIter1, class _InIter2, class _OutIter>
37*4bdff4beSrobert using merge_result = in_in_out_result<_InIter1, _InIter2, _OutIter>;
38*4bdff4beSrobert 
39*4bdff4beSrobert namespace __merge {
40*4bdff4beSrobert 
41*4bdff4beSrobert template <
42*4bdff4beSrobert     class _InIter1,
43*4bdff4beSrobert     class _Sent1,
44*4bdff4beSrobert     class _InIter2,
45*4bdff4beSrobert     class _Sent2,
46*4bdff4beSrobert     class _OutIter,
47*4bdff4beSrobert     class _Comp,
48*4bdff4beSrobert     class _Proj1,
49*4bdff4beSrobert     class _Proj2>
50*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI constexpr merge_result<__remove_cvref_t<_InIter1>, __remove_cvref_t<_InIter2>, __remove_cvref_t<_OutIter>>
__merge_impl(_InIter1 && __first1,_Sent1 && __last1,_InIter2 && __first2,_Sent2 && __last2,_OutIter && __result,_Comp && __comp,_Proj1 && __proj1,_Proj2 && __proj2)51*4bdff4beSrobert __merge_impl(
52*4bdff4beSrobert     _InIter1&& __first1,
53*4bdff4beSrobert     _Sent1&& __last1,
54*4bdff4beSrobert     _InIter2&& __first2,
55*4bdff4beSrobert     _Sent2&& __last2,
56*4bdff4beSrobert     _OutIter&& __result,
57*4bdff4beSrobert     _Comp&& __comp,
58*4bdff4beSrobert     _Proj1&& __proj1,
59*4bdff4beSrobert     _Proj2&& __proj2) {
60*4bdff4beSrobert   for (; __first1 != __last1 && __first2 != __last2; ++__result) {
61*4bdff4beSrobert     if (std::invoke(__comp, std::invoke(__proj2, *__first2), std::invoke(__proj1, *__first1))) {
62*4bdff4beSrobert       *__result = *__first2;
63*4bdff4beSrobert       ++__first2;
64*4bdff4beSrobert     } else {
65*4bdff4beSrobert       *__result = *__first1;
66*4bdff4beSrobert       ++__first1;
67*4bdff4beSrobert     }
68*4bdff4beSrobert   }
69*4bdff4beSrobert   auto __ret1 = ranges::copy(std::move(__first1), std::move(__last1), std::move(__result));
70*4bdff4beSrobert   auto __ret2 = ranges::copy(std::move(__first2), std::move(__last2), std::move(__ret1.out));
71*4bdff4beSrobert   return {std::move(__ret1.in), std::move(__ret2.in), std::move(__ret2.out)};
72*4bdff4beSrobert }
73*4bdff4beSrobert 
74*4bdff4beSrobert struct __fn {
75*4bdff4beSrobert   template <
76*4bdff4beSrobert       input_iterator _InIter1,
77*4bdff4beSrobert       sentinel_for<_InIter1> _Sent1,
78*4bdff4beSrobert       input_iterator _InIter2,
79*4bdff4beSrobert       sentinel_for<_InIter2> _Sent2,
80*4bdff4beSrobert       weakly_incrementable _OutIter,
81*4bdff4beSrobert       class _Comp  = less,
82*4bdff4beSrobert       class _Proj1 = identity,
83*4bdff4beSrobert       class _Proj2 = identity>
84*4bdff4beSrobert     requires mergeable<_InIter1, _InIter2, _OutIter, _Comp, _Proj1, _Proj2>
operator__fn85*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI constexpr merge_result<_InIter1, _InIter2, _OutIter> operator()(
86*4bdff4beSrobert       _InIter1 __first1,
87*4bdff4beSrobert       _Sent1 __last1,
88*4bdff4beSrobert       _InIter2 __first2,
89*4bdff4beSrobert       _Sent2 __last2,
90*4bdff4beSrobert       _OutIter __result,
91*4bdff4beSrobert       _Comp __comp   = {},
92*4bdff4beSrobert       _Proj1 __proj1 = {},
93*4bdff4beSrobert       _Proj2 __proj2 = {}) const {
94*4bdff4beSrobert     return __merge::__merge_impl(__first1, __last1, __first2, __last2, __result, __comp, __proj1, __proj2);
95*4bdff4beSrobert   }
96*4bdff4beSrobert 
97*4bdff4beSrobert   template <
98*4bdff4beSrobert       input_range _Range1,
99*4bdff4beSrobert       input_range _Range2,
100*4bdff4beSrobert       weakly_incrementable _OutIter,
101*4bdff4beSrobert       class _Comp  = less,
102*4bdff4beSrobert       class _Proj1 = identity,
103*4bdff4beSrobert       class _Proj2 = identity>
104*4bdff4beSrobert     requires mergeable<
105*4bdff4beSrobert         iterator_t<_Range1>,
106*4bdff4beSrobert         iterator_t<_Range2>,
107*4bdff4beSrobert         _OutIter,
108*4bdff4beSrobert         _Comp,
109*4bdff4beSrobert         _Proj1,
110*4bdff4beSrobert         _Proj2>
111*4bdff4beSrobert   _LIBCPP_HIDE_FROM_ABI constexpr merge_result<borrowed_iterator_t<_Range1>, borrowed_iterator_t<_Range2>, _OutIter>
operator__fn112*4bdff4beSrobert         operator()(
113*4bdff4beSrobert             _Range1&& __range1,
114*4bdff4beSrobert             _Range2&& __range2,
115*4bdff4beSrobert             _OutIter __result,
116*4bdff4beSrobert             _Comp __comp   = {},
117*4bdff4beSrobert             _Proj1 __proj1 = {},
118*4bdff4beSrobert             _Proj2 __proj2 = {}) const {
119*4bdff4beSrobert     return __merge::__merge_impl(
120*4bdff4beSrobert         ranges::begin(__range1),
121*4bdff4beSrobert         ranges::end(__range1),
122*4bdff4beSrobert         ranges::begin(__range2),
123*4bdff4beSrobert         ranges::end(__range2),
124*4bdff4beSrobert         __result,
125*4bdff4beSrobert         __comp,
126*4bdff4beSrobert         __proj1,
127*4bdff4beSrobert         __proj2);
128*4bdff4beSrobert   }
129*4bdff4beSrobert };
130*4bdff4beSrobert 
131*4bdff4beSrobert } // namespace __merge
132*4bdff4beSrobert 
133*4bdff4beSrobert inline namespace __cpo {
134*4bdff4beSrobert   inline constexpr auto merge = __merge::__fn{};
135*4bdff4beSrobert } // namespace __cpo
136*4bdff4beSrobert } // namespace ranges
137*4bdff4beSrobert 
138*4bdff4beSrobert _LIBCPP_END_NAMESPACE_STD
139*4bdff4beSrobert 
140*4bdff4beSrobert #endif // _LIBCPP_STD_VER > 17
141*4bdff4beSrobert 
142*4bdff4beSrobert #endif // _LIBCPP___ALGORITHM_RANGES_MERGE_H
143