Skip to content

Define begin() and end() methods in simple views#2673

Closed
dmitriy-sobolev wants to merge 8 commits into
mainfrom
dev/dmitriy-sobolev/fix-scan-by-segment-zip
Closed

Define begin() and end() methods in simple views#2673
dmitriy-sobolev wants to merge 8 commits into
mainfrom
dev/dmitriy-sobolev/fix-scan-by-segment-zip

Conversation

@dmitriy-sobolev
Copy link
Copy Markdown
Contributor

@dmitriy-sobolev dmitriy-sobolev commented Apr 29, 2026

It fixes a regression in inclusive_scan_by_segment_zip.pass, exclusive_scan_by_segment_zip.pass and shift_left_right.pass caused by #2618, which added these methods into drop_view_simple.

Example of an issue:

Building CXX object test/CMakeFiles/exclusive_scan_by_segment_zip.pass.dir/parallel_api/numeric/numeric.ops/exclusive_scan_by_segment_zip.pass.cpp.o
In file included from oneDPL/test/parallel_api/numeric/numeric.ops/exclusive_scan_by_segment_zip.pass.cpp:18:
In file included from oneDPL/include/oneapi/dpl/execution:75:
In file included from oneDPL/include/oneapi/dpl/pstl/algorithm_impl.h:29:
In file included from oneDPL/include/oneapi/dpl/pstl/execution_impl.h:22:
In file included from oneDPL/include/oneapi/dpl/pstl/parallel_backend.h:32:
In file included from oneDPL/include/oneapi/dpl/pstl/hetero/dpcpp/parallel_backend_sycl.h:35:
oneDPL/include/oneapi/dpl/pstl/hetero/dpcpp/../../utils_ranges.h:543:16: error: no matching function for call to '__begin'
  543 |         return __begin(__r) + __n;
      |                ^~~~~~~
/usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/iterator_concepts.h:979:23: note: in instantiation of member function 'oneapi::dpl::__ranges::drop_view_simple<oneapi::dpl::__ranges::zip_view<oneapi::dpl::__ranges::guard_view<int *>,
      oneapi::dpl::__ranges::guard_view<int *>>, int>::begin' requested here
  979 |           { __decay_copy(__t.begin()) } -> input_or_output_iterator;
      |                              ^
/usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/iterator_concepts.h:979:6: note: in instantiation of requirement here
  979 |           { __decay_copy(__t.begin()) } -> input_or_output_iterator;
      |             ^~~~~~~~~~~~~~~~~~~~~~~~~
/usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/iterator_concepts.h:977:32: note: while substituting template arguments into constraint expression here
  977 |       concept __member_begin = requires(_Tp& __t)
      |                                ^~~~~~~~~~~~~~~~~~
  978 |         {
      |         ~
  979 |           { __decay_copy(__t.begin()) } -> input_or_output_iterator;
      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  980 |         };
      |         ~
/usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/ranges_base.h:112:50: note: while checking the satisfaction of concept
      '__member_begin<oneapi::dpl::__ranges::drop_view_simple<oneapi::dpl::__ranges::zip_view<oneapi::dpl::__ranges::guard_view<int *>, oneapi::dpl::__ranges::guard_view<int *>>, int> &>' requested here
  112 |         requires is_array_v<remove_reference_t<_Tp>> || __member_begin<_Tp>
      |                                                         ^~~~~~~~~~~~~~~~~~~
oneDPL/include/oneapi/dpl/pstl/hetero/dpcpp/../../utils_ranges.h:44:37: note: while checking constraint satisfaction for template
      'operator()<oneapi::dpl::__ranges::drop_view_simple<oneapi::dpl::__ranges::zip_view<oneapi::dpl::__ranges::guard_view<int *>, oneapi::dpl::__ranges::guard_view<int *>>, int> &>' required here
   44 | __begin(_Range&& __rng) -> decltype(std::ranges::begin(std::forward<_Range>(__rng)))
      |                                     ^~~
oneDPL/include/oneapi/dpl/pstl/hetero/dpcpp/../../utils_ranges.h:44:37: note: while substituting deduced template arguments into function template 'operator()' [with _Tp =
      oneapi::dpl::__ranges::drop_view_simple<oneapi::dpl::__ranges::zip_view<oneapi::dpl::__ranges::guard_view<int *>, oneapi::dpl::__ranges::guard_view<int *>>, int> &]
oneDPL/include/oneapi/dpl/pstl/hetero/dpcpp/../../utils_ranges.h:151:48: note: while substituting deduced template arguments into function template '__begin' [with _Range =
      oneapi::dpl::__ranges::drop_view_simple<oneapi::dpl::__ranges::zip_view<oneapi::dpl::__ranges::guard_view<int *>, oneapi::dpl::__ranges::guard_view<int *>>, int> &]
  151 |                          std::decay_t<decltype(oneapi::dpl::__ranges::__begin(std::declval<_R&>()))>>::value_type;
      |                                                ^
oneDPL/include/oneapi/dpl/pstl/hetero/dpcpp/../../utils_ranges.h:168:28: note: while substituting explicitly-specified template arguments into function template 'get_value_type'
  168 | using __value_t = decltype(oneapi::dpl::__internal::get_value_type<_R>(0));
      |                            ^
oneDPL/include/oneapi/dpl/pstl/hetero/dpcpp/parallel_backend_sycl_for.h:46:61: note: in instantiation of template type alias '__value_t' requested here
   46 |     using _ValueTypes = std::tuple<oneapi::dpl::__internal::__value_t<_Ranges>...>;
      |                                                             ^
oneDPL/include/oneapi/dpl/pstl/hetero/dpcpp/parallel_backend_sycl_for.h:252:19: note: in instantiation of template class 'oneapi::dpl::__par_backend_hetero::__pfor_params<true,
      oneapi::dpl::unseq_backend::walk_n_vectors_or_scalars<oneapi::dpl::__internal::__transform_functor<oneapi::dpl::__internal::__not_pred<std::equal_to<void>>>>, oneapi::dpl::__ranges::zip_view<oneapi::dpl::__ranges::guard_view<int *>,
      oneapi::dpl::__ranges::guard_view<int *>> &, oneapi::dpl::__ranges::drop_view_simple<oneapi::dpl::__ranges::zip_view<oneapi::dpl::__ranges::guard_view<int *>, oneapi::dpl::__ranges::guard_view<int *>>, int> &,
      oneapi::dpl::__ranges::all_view<unsigned int, sycl::access::mode::read_write> &>' requested here
  252 |     if constexpr (__params_t::__iters_per_item > 1 || __params_t::__vector_size > 1)
      |                   ^
oneDPL/include/oneapi/dpl/pstl/hetero/dpcpp/parallel_backend_sycl_for.h:271:47: note: in instantiation of function template specialization
      'oneapi::dpl::__par_backend_hetero::__parallel_for_impl<oneapi::dpl::__par_backend_hetero::__scan_by_seg_transform_wrapper1<oneapi::dpl::__par_backend_hetero::__scan_by_seg_fallback<oneapi::dpl::execution::DefaultKernelName>>,
      oneapi::dpl::unseq_backend::walk_n_vectors_or_scalars<oneapi::dpl::__internal::__transform_functor<oneapi::dpl::__internal::__not_pred<std::equal_to<void>>>>, unsigned long, oneapi::dpl::__ranges::zip_view<oneapi::dpl::__ranges::guard_view<int *>,
      oneapi::dpl::__ranges::guard_view<int *>> &, oneapi::dpl::__ranges::drop_view_simple<oneapi::dpl::__ranges::zip_view<oneapi::dpl::__ranges::guard_view<int *>, oneapi::dpl::__ranges::guard_view<int *>>, int> &,
      oneapi::dpl::__ranges::all_view<unsigned int, sycl::access::mode::read_write> &>' requested here
  271 |     return oneapi::dpl::__par_backend_hetero::__parallel_for_impl<_CustomName>(__q_local, __brick, __count,
      |                                               ^
oneDPL/include/oneapi/dpl/pstl/hetero/dpcpp/parallel_backend_sycl.h:2418:9: note: in instantiation of function template specialization
      'oneapi::dpl::__par_backend_hetero::__parallel_for<oneapi::dpl::execution::device_policy<oneapi::dpl::__par_backend_hetero::__scan_by_seg_transform_wrapper1<oneapi::dpl::__par_backend_hetero::__scan_by_seg_fallback<oneapi::dpl::execution::DefaultKernelName>>>,
      oneapi::dpl::unseq_backend::walk_n_vectors_or_scalars<oneapi::dpl::__internal::__transform_functor<oneapi::dpl::__internal::__not_pred<std::equal_to<void>>>>, unsigned long, oneapi::dpl::__ranges::zip_view<oneapi::dpl::__ranges::guard_view<int *>,
      oneapi::dpl::__ranges::guard_view<int *>> &, oneapi::dpl::__ranges::drop_view_simple<oneapi::dpl::__ranges::zip_view<oneapi::dpl::__ranges::guard_view<int *>, oneapi::dpl::__ranges::guard_view<int *>>, int> &,
      oneapi::dpl::__ranges::all_view<unsigned int, sycl::access::mode::read_write> &>' requested here
 2418 |         __parallel_for(oneapi::dpl::__internal::__device_backend_tag{},
      |         ^
oneDPL/include/oneapi/dpl/pstl/hetero/dpcpp/parallel_backend_sycl.h:2509:5: note: in instantiation of function template specialization
      'oneapi::dpl::__par_backend_hetero::__parallel_scan_by_segment_fallback<oneapi::dpl::execution::DefaultKernelName, false,
      oneapi::dpl::execution::device_policy<oneapi::dpl::__par_backend_hetero::__scan_by_seg_fallback<oneapi::dpl::execution::DefaultKernelName>>, oneapi::dpl::__ranges::zip_view<oneapi::dpl::__ranges::guard_view<int *>,
      oneapi::dpl::__ranges::guard_view<int *>>, oneapi::dpl::__ranges::zip_view<oneapi::dpl::__ranges::guard_view<int *>, oneapi::dpl::__ranges::guard_view<int *>>, oneapi::dpl::__ranges::zip_view<oneapi::dpl::__ranges::guard_view<int *>,
      oneapi::dpl::__ranges::guard_view<int *>>, std::equal_to<void>, TestUtils::TupleAddFunctor1, oneapi::dpl::unseq_backend::__init_value<std::tuple<int, int>>>' requested here
 2509 |     __parallel_scan_by_segment_fallback<_CustomName, __is_inclusive>(
      |     ^
oneDPL/include/oneapi/dpl/pstl/hetero/numeric_impl_hetero.h:338:13: note: in instantiation of function template specialization 'oneapi::dpl::__par_backend_hetero::__parallel_scan_by_segment<false, const
      oneapi::dpl::execution::device_policy<> &, oneapi::dpl::__ranges::zip_view<oneapi::dpl::__ranges::guard_view<int *>, oneapi::dpl::__ranges::guard_view<int *>>, oneapi::dpl::__ranges::zip_view<oneapi::dpl::__ranges::guard_view<int *>,
      oneapi::dpl::__ranges::guard_view<int *>>, oneapi::dpl::__ranges::zip_view<oneapi::dpl::__ranges::guard_view<int *>, oneapi::dpl::__ranges::guard_view<int *>>, std::equal_to<void>, TestUtils::TupleAddFunctor1,
      oneapi::dpl::unseq_backend::__init_value<std::tuple<int, int>>>' requested here
  338 |     __bknd::__parallel_scan_by_segment<_Inclusive::value>(
      |             ^
oneDPL/include/oneapi/dpl/pstl/hetero/numeric_impl_hetero.h:351:12: note: in instantiation of function template specialization 'oneapi::dpl::__internal::__pattern_scan_by_segment_impl<oneapi::dpl::__internal::__device_backend_tag,
      const oneapi::dpl::execution::device_policy<> &, oneapi::dpl::zip_iterator<int *, int *>, oneapi::dpl::zip_iterator<int *, int *>, oneapi::dpl::zip_iterator<int *, int *>, std::equal_to<void>, TestUtils::TupleAddFunctor1,
      std::integral_constant<bool, false>, oneapi::dpl::unseq_backend::__init_value<std::tuple<int, int>>>' requested here
  351 |     return __pattern_scan_by_segment_impl(__tag, std::forward<_Policy>(__policy), __first1, __last1, __first2, __result,
      |            ^
oneDPL/include/oneapi/dpl/internal/exclusive_scan_by_segment_impl.h:104:24: note: in instantiation of function template specialization 'oneapi::dpl::__internal::__pattern_scan_by_segment<oneapi::dpl::__internal::__device_backend_tag,
      const oneapi::dpl::execution::device_policy<> &, oneapi::dpl::zip_iterator<int *, int *>, oneapi::dpl::zip_iterator<int *, int *>, oneapi::dpl::zip_iterator<int *, int *>, std::equal_to<void>, TestUtils::TupleAddFunctor1,
      std::integral_constant<bool, false>, std::tuple<int, int>>' requested here
  104 |     return __internal::__pattern_scan_by_segment(__tag, std::forward<Policy>(policy), first1, last1, first2, result,
      |                        ^
oneDPL/include/oneapi/dpl/internal/exclusive_scan_by_segment_impl.h:119:24: note: in instantiation of function template specialization
      'oneapi::dpl::__internal::__pattern_exclusive_scan_by_segment<oneapi::dpl::__internal::__device_backend_tag, const oneapi::dpl::execution::device_policy<> &, oneapi::dpl::zip_iterator<int *, int *>, oneapi::dpl::zip_iterator<int *, int *>,
      oneapi::dpl::zip_iterator<int *, int *>, std::tuple<int, int>, std::equal_to<void>, TestUtils::TupleAddFunctor1>' requested here
  119 |     return __internal::__pattern_exclusive_scan_by_segment(__dispatch_tag, std::forward<Policy>(policy), first1, last1,
      |                        ^
oneDPL/test/parallel_api/numeric/numeric.ops/exclusive_scan_by_segment_zip.pass.cpp:70:18: note: in instantiation of function template specialization 'oneapi::dpl::exclusive_scan_by_segment<const oneapi::dpl::execution::device_policy<>
      &, oneapi::dpl::zip_iterator<int *, int *>, oneapi::dpl::zip_iterator<int *, int *>, oneapi::dpl::zip_iterator<int *, int *>, std::tuple<int, int>, std::equal_to<void>, TestUtils::TupleAddFunctor1>' requested here
   70 |     oneapi::dpl::exclusive_scan_by_segment(
      |                  ^
oneDPL/test/parallel_api/numeric/numeric.ops/exclusive_scan_by_segment_zip.pass.cpp:97:5: note: in instantiation of function template specialization 'test_with_usm<sycl::usm::alloc::shared, KernelName1, const
      oneapi::dpl::execution::device_policy<> &>' requested here
   97 |     test_with_usm<sycl::usm::alloc::shared, KernelName1>(CLONE_TEST_POLICY(exec));
      |     ^
oneDPL/test/parallel_api/numeric/numeric.ops/exclusive_scan_by_segment_zip.pass.cpp:108:5: note: in instantiation of function template specialization 'test_impl<oneapi::dpl::execution::device_policy<> &>' requested here
  108 |     test_impl(policy);
      |     ^
oneDPL/include/oneapi/dpl/pstl/hetero/dpcpp/../../utils_ranges.h:44:1: note: candidate template ignored: substitution failure [with _Range = const oneapi::dpl::__ranges::zip_view<oneapi::dpl::__ranges::guard_view<int *>,
      oneapi::dpl::__ranges::guard_view<int *>> &]: no matching function for call to object of type 'const __cust_access::_Begin'
   44 | __begin(_Range&& __rng) -> decltype(std::ranges::begin(std::forward<_Range>(__rng)))
      | ^                                   ~~~
1 error generated.

Alternative approaches:

  • Add a trailing return type to begin()/end() from drop_view_simple with immediate context, see f6616eb. It lets

get_value_type(long) -> typename std::iterator_traits<
std::decay_t<decltype(oneapi::dpl::__ranges::__begin(std::declval<_R&>()))>>::value_type;

deduce __begin's return type without instantiating its body. Instantiation of a body will lead the the issue above.

  • Remove begin()/end() from drop_view_simple, and probably use something else in struct __internal::__ends_with_fn.

I added begin()/end() to the rest views, assuming a view must have them.

@dmitriy-sobolev dmitriy-sobolev force-pushed the dev/dmitriy-sobolev/fix-scan-by-segment-zip branch from e3a15ce to 43e5da3 Compare April 29, 2026 13:59
@danhoeflinger
Copy link
Copy Markdown
Contributor

From the CI errors, it seems like there are more views which may need this treatment, and it may reach into nanorange code. Its not clear to me how deep that rabbit hole goes. I don't see a ton of utility in retrofitting these legacy simple views other than resolving this specific build error.

The path of least resistance here may be just making this begin / end functionality enabled if the underlying range supports it: #2674 .

@dmitriy-sobolev
Copy link
Copy Markdown
Contributor Author

The path of least resistance here may be just making this begin / end functionality enabled if the underlying range supports it

I like this perspective. I initially viewed it as a workaround to avoid body instantiation, but provide the return type.

I'm closing the PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants