xref: /freebsd-src/contrib/llvm-project/libcxx/include/__algorithm/ranges_transform.h (revision b3edf4467982447620505a28fc82e38a414c07dc)
181ad6265SDimitry Andric //===----------------------------------------------------------------------===//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
881ad6265SDimitry Andric 
981ad6265SDimitry Andric #ifndef _LIBCPP___ALGORITHM_RANGES_TRANSFORM_H
1081ad6265SDimitry Andric #define _LIBCPP___ALGORITHM_RANGES_TRANSFORM_H
1181ad6265SDimitry Andric 
1281ad6265SDimitry Andric #include <__algorithm/in_in_out_result.h>
1381ad6265SDimitry Andric #include <__algorithm/in_out_result.h>
1481ad6265SDimitry Andric #include <__concepts/constructible.h>
1581ad6265SDimitry Andric #include <__config>
1681ad6265SDimitry Andric #include <__functional/identity.h>
1781ad6265SDimitry Andric #include <__functional/invoke.h>
1881ad6265SDimitry Andric #include <__iterator/concepts.h>
1981ad6265SDimitry Andric #include <__iterator/projected.h>
2081ad6265SDimitry Andric #include <__ranges/access.h>
2181ad6265SDimitry Andric #include <__ranges/concepts.h>
2281ad6265SDimitry Andric #include <__ranges/dangling.h>
2381ad6265SDimitry Andric #include <__utility/move.h>
2481ad6265SDimitry Andric 
2581ad6265SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
2681ad6265SDimitry Andric #  pragma GCC system_header
2781ad6265SDimitry Andric #endif
2881ad6265SDimitry Andric 
29*b3edf446SDimitry Andric _LIBCPP_PUSH_MACROS
30*b3edf446SDimitry Andric #include <__undef_macros>
31*b3edf446SDimitry Andric 
3206c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20
3381ad6265SDimitry Andric 
3481ad6265SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
3581ad6265SDimitry Andric 
3681ad6265SDimitry Andric namespace ranges {
3781ad6265SDimitry Andric 
3881ad6265SDimitry Andric template <class _Ip, class _Op>
3981ad6265SDimitry Andric using unary_transform_result = in_out_result<_Ip, _Op>;
4081ad6265SDimitry Andric 
4181ad6265SDimitry Andric template <class _I1, class _I2, class _O1>
4281ad6265SDimitry Andric using binary_transform_result = in_in_out_result<_I1, _I2, _O1>;
4381ad6265SDimitry Andric 
4481ad6265SDimitry Andric namespace __transform {
4581ad6265SDimitry Andric struct __fn {
4681ad6265SDimitry Andric private:
4706c3fb27SDimitry Andric   template <class _InIter, class _Sent, class _OutIter, class _Func, class _Proj>
4806c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI static constexpr unary_transform_result<_InIter, _OutIter>
__unary__fn4906c3fb27SDimitry Andric   __unary(_InIter __first, _Sent __last, _OutIter __result, _Func& __operation, _Proj& __projection) {
5081ad6265SDimitry Andric     while (__first != __last) {
5181ad6265SDimitry Andric       *__result = std::invoke(__operation, std::invoke(__projection, *__first));
5281ad6265SDimitry Andric       ++__first;
5381ad6265SDimitry Andric       ++__result;
5481ad6265SDimitry Andric     }
5581ad6265SDimitry Andric 
5681ad6265SDimitry Andric     return {std::move(__first), std::move(__result)};
5781ad6265SDimitry Andric   }
5881ad6265SDimitry Andric 
5906c3fb27SDimitry Andric   template <class _InIter1,
6006c3fb27SDimitry Andric             class _Sent1,
6106c3fb27SDimitry Andric             class _InIter2,
6206c3fb27SDimitry Andric             class _Sent2,
6381ad6265SDimitry Andric             class _OutIter,
6481ad6265SDimitry Andric             class _Func,
6581ad6265SDimitry Andric             class _Proj1,
6681ad6265SDimitry Andric             class _Proj2>
6781ad6265SDimitry Andric   _LIBCPP_HIDE_FROM_ABI static constexpr binary_transform_result<_InIter1, _InIter2, _OutIter>
__binary__fn6806c3fb27SDimitry Andric   __binary(_InIter1 __first1,
6906c3fb27SDimitry Andric            _Sent1 __last1,
7006c3fb27SDimitry Andric            _InIter2 __first2,
7106c3fb27SDimitry Andric            _Sent2 __last2,
7281ad6265SDimitry Andric            _OutIter __result,
7381ad6265SDimitry Andric            _Func& __binary_operation,
7481ad6265SDimitry Andric            _Proj1& __projection1,
7581ad6265SDimitry Andric            _Proj2& __projection2) {
7681ad6265SDimitry Andric     while (__first1 != __last1 && __first2 != __last2) {
7706c3fb27SDimitry Andric       *__result =
7806c3fb27SDimitry Andric           std::invoke(__binary_operation, std::invoke(__projection1, *__first1), std::invoke(__projection2, *__first2));
7981ad6265SDimitry Andric       ++__first1;
8081ad6265SDimitry Andric       ++__first2;
8181ad6265SDimitry Andric       ++__result;
8281ad6265SDimitry Andric     }
8381ad6265SDimitry Andric     return {std::move(__first1), std::move(__first2), std::move(__result)};
8481ad6265SDimitry Andric   }
8506c3fb27SDimitry Andric 
8681ad6265SDimitry Andric public:
8706c3fb27SDimitry Andric   template <input_iterator _InIter,
8806c3fb27SDimitry Andric             sentinel_for<_InIter> _Sent,
8981ad6265SDimitry Andric             weakly_incrementable _OutIter,
9081ad6265SDimitry Andric             copy_constructible _Func,
9181ad6265SDimitry Andric             class _Proj = identity>
9281ad6265SDimitry Andric     requires indirectly_writable<_OutIter, indirect_result_t<_Func&, projected<_InIter, _Proj>>>
9306c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr unary_transform_result<_InIter, _OutIter>
operator__fn9406c3fb27SDimitry Andric   operator()(_InIter __first, _Sent __last, _OutIter __result, _Func __operation, _Proj __proj = {}) const {
9581ad6265SDimitry Andric     return __unary(std::move(__first), std::move(__last), std::move(__result), __operation, __proj);
9681ad6265SDimitry Andric   }
9781ad6265SDimitry Andric 
9806c3fb27SDimitry Andric   template <input_range _Range, weakly_incrementable _OutIter, copy_constructible _Func, class _Proj = identity>
9981ad6265SDimitry Andric     requires indirectly_writable<_OutIter, indirect_result_t<_Func, projected<iterator_t<_Range>, _Proj>>>
10006c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr unary_transform_result<borrowed_iterator_t<_Range>, _OutIter>
operator__fn10106c3fb27SDimitry Andric   operator()(_Range&& __range, _OutIter __result, _Func __operation, _Proj __projection = {}) const {
10281ad6265SDimitry Andric     return __unary(ranges::begin(__range), ranges::end(__range), std::move(__result), __operation, __projection);
10381ad6265SDimitry Andric   }
10481ad6265SDimitry Andric 
10506c3fb27SDimitry Andric   template <input_iterator _InIter1,
10606c3fb27SDimitry Andric             sentinel_for<_InIter1> _Sent1,
10706c3fb27SDimitry Andric             input_iterator _InIter2,
10806c3fb27SDimitry Andric             sentinel_for<_InIter2> _Sent2,
10981ad6265SDimitry Andric             weakly_incrementable _OutIter,
11081ad6265SDimitry Andric             copy_constructible _Func,
11181ad6265SDimitry Andric             class _Proj1 = identity,
11281ad6265SDimitry Andric             class _Proj2 = identity>
11306c3fb27SDimitry Andric     requires indirectly_writable<_OutIter,
11406c3fb27SDimitry Andric                                  indirect_result_t<_Func&, projected<_InIter1, _Proj1>, projected<_InIter2, _Proj2>>>
operator__fn11506c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr binary_transform_result<_InIter1, _InIter2, _OutIter> operator()(
11606c3fb27SDimitry Andric       _InIter1 __first1,
11706c3fb27SDimitry Andric       _Sent1 __last1,
11806c3fb27SDimitry Andric       _InIter2 __first2,
11906c3fb27SDimitry Andric       _Sent2 __last2,
12081ad6265SDimitry Andric       _OutIter __result,
12181ad6265SDimitry Andric       _Func __binary_operation,
12281ad6265SDimitry Andric       _Proj1 __projection1 = {},
12381ad6265SDimitry Andric       _Proj2 __projection2 = {}) const {
12406c3fb27SDimitry Andric     return __binary(
12506c3fb27SDimitry Andric         std::move(__first1),
12606c3fb27SDimitry Andric         std::move(__last1),
12706c3fb27SDimitry Andric         std::move(__first2),
12806c3fb27SDimitry Andric         std::move(__last2),
12981ad6265SDimitry Andric         std::move(__result),
13081ad6265SDimitry Andric         __binary_operation,
13181ad6265SDimitry Andric         __projection1,
13281ad6265SDimitry Andric         __projection2);
13381ad6265SDimitry Andric   }
13481ad6265SDimitry Andric 
13581ad6265SDimitry Andric   template <input_range _Range1,
13681ad6265SDimitry Andric             input_range _Range2,
13781ad6265SDimitry Andric             weakly_incrementable _OutIter,
13881ad6265SDimitry Andric             copy_constructible _Func,
13981ad6265SDimitry Andric             class _Proj1 = identity,
14081ad6265SDimitry Andric             class _Proj2 = identity>
14106c3fb27SDimitry Andric     requires indirectly_writable<
14206c3fb27SDimitry Andric         _OutIter,
14306c3fb27SDimitry Andric         indirect_result_t<_Func&, projected<iterator_t<_Range1>, _Proj1>, projected<iterator_t<_Range2>, _Proj2>>>
14406c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr binary_transform_result<borrowed_iterator_t<_Range1>,
14506c3fb27SDimitry Andric                                                           borrowed_iterator_t<_Range2>,
14606c3fb27SDimitry Andric                                                           _OutIter>
operator__fn14781ad6265SDimitry Andric   operator()(_Range1&& __range1,
14881ad6265SDimitry Andric              _Range2&& __range2,
14981ad6265SDimitry Andric              _OutIter __result,
15081ad6265SDimitry Andric              _Func __binary_operation,
15181ad6265SDimitry Andric              _Proj1 __projection1 = {},
15281ad6265SDimitry Andric              _Proj2 __projection2 = {}) const {
15306c3fb27SDimitry Andric     return __binary(
15406c3fb27SDimitry Andric         ranges::begin(__range1),
15506c3fb27SDimitry Andric         ranges::end(__range1),
15606c3fb27SDimitry Andric         ranges::begin(__range2),
15706c3fb27SDimitry Andric         ranges::end(__range2),
15881ad6265SDimitry Andric         std::move(__result),
15981ad6265SDimitry Andric         __binary_operation,
16081ad6265SDimitry Andric         __projection1,
16181ad6265SDimitry Andric         __projection2);
16281ad6265SDimitry Andric   }
16381ad6265SDimitry Andric };
16481ad6265SDimitry Andric } // namespace __transform
16581ad6265SDimitry Andric 
16681ad6265SDimitry Andric inline namespace __cpo {
16781ad6265SDimitry Andric inline constexpr auto transform = __transform::__fn{};
16881ad6265SDimitry Andric } // namespace __cpo
16981ad6265SDimitry Andric } // namespace ranges
17081ad6265SDimitry Andric 
17181ad6265SDimitry Andric _LIBCPP_END_NAMESPACE_STD
17281ad6265SDimitry Andric 
17306c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 20
17481ad6265SDimitry Andric 
175*b3edf446SDimitry Andric _LIBCPP_POP_MACROS
176*b3edf446SDimitry Andric 
17781ad6265SDimitry Andric #endif // _LIBCPP___ALGORITHM_RANGES_TRANSFORM_H
178