oneTBB icon indicating copy to clipboard operation
oneTBB copied to clipboard

tbb::blocked_range does not fulfill the c++20 concept std::ranges::range

Open dbs4261 opened this issue 9 months ago • 2 comments

Summary

One would think, based on the name that a tbb::blocked_range<T> fulfills the c++20 concept std::ranges::range, similar to a std::views::iota(tbb_range.begin(), tbb_range.end()). This is not the case, as far as I can tell, because tbb::blocked_range<T> returns a value type from tbb::blocked_range<T>::begin(). That value type is not an iterator because it cannot be de-referenced. std::views::iota deals with this with an exposition only class that wraps around the value type that is implicitly convertible to the value type. tbb::blocked_range<T> should return a similar wrapper so that tbb::blocked_range<T>s are actual c++20 ranges.

Version

tbb v2021.8.0

Observed Behavior

static_assert(std::ranges::range<tbb::blocked_range<std::size_t>>) fails

Expected Behavior

static_assert(std::ranges::range<tbb::blocked_range<std::size_t>>) passes

dbs4261 avatar Mar 27 '25 20:03 dbs4261

@dbs4261,

Thank you for your question. blocked_range class was not initially designed to be a range in a C++20 meaning. It can only be used as an input for TBB parallel algorithms like parallel_for that currently do not support C++ ranges. Even for the blocked_range<iterator> that models the C++20 range in fact, it still can be used as the input for parallel algorithms unchanged. blocked_range piped with some other C++20 view cannot be used as the input since it does not model the TBB range . Could you please share more details on when you believe it may be useful to have blocked_range<size_t> modeling the std::ranges::range concept?

kboyarinov avatar Mar 31 '25 10:03 kboyarinov

@kboyarinov,

As for what I had in mind, I was actually looking to do something like this to get a more pythonic for loop. It would actually be really handy for use with the templated blocked_nd_range.

for (auto [p, r, c]: std::ranges::views::cartesian_product(r.pages(), r.rows(), r.cols())) {
    ...
}

I think the main thing to focus on is that I made this comment because I assumed that something with a begin and end that was called a range would fulfill the concept. I don't think that assumption is unreasonable, but I totally understand that blocked_range predates c++ ranges. I brought up std::ranges::views::iota because it does basically the same thing as a blocked_range. And I think adding this functionality is doable in a backwards compatible way.

As an aside, In my mind range::is_divisible() range::(R&, split) and range::(R&, proportional_split) make more sense as part of the Splittable named requirements.

dbs4261 avatar Mar 31 '25 17:03 dbs4261