File indexing completed on 2025-07-30 08:46:18
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #ifndef __TBB_detail__range_common_H
0018 #define __TBB_detail__range_common_H
0019
0020 #include "_config.h"
0021 #include "_utils.h"
0022 #if __TBB_CPP20_CONCEPTS_PRESENT
0023 #include <concepts>
0024 #endif
0025 #include <iterator>
0026
0027 namespace tbb {
0028 namespace detail {
0029 inline namespace d0 {
0030
0031
0032
0033
0034
0035
0036 class split {};
0037
0038
0039
0040
0041
0042
0043 class proportional_split : no_assign {
0044 public:
0045 proportional_split(size_t _left = 1, size_t _right = 1) : my_left(_left), my_right(_right) { }
0046
0047 size_t left() const { return my_left; }
0048 size_t right() const { return my_right; }
0049
0050
0051 explicit operator split() const { return split(); }
0052
0053 private:
0054 size_t my_left, my_right;
0055 };
0056
0057 template <typename Range, typename = void>
0058 struct range_split_object_provider {
0059 template <typename PartitionerSplitType>
0060 static split get( PartitionerSplitType& ) { return split(); }
0061 };
0062
0063 template <typename Range>
0064 struct range_split_object_provider<Range,
0065 typename std::enable_if<std::is_constructible<Range, Range&, proportional_split&>::value>::type> {
0066 template <typename PartitionerSplitType>
0067 static PartitionerSplitType& get( PartitionerSplitType& split_obj ) { return split_obj; }
0068 };
0069
0070 template <typename Range, typename PartitionerSplitType>
0071 auto get_range_split_object( PartitionerSplitType& split_obj )
0072 -> decltype(range_split_object_provider<Range>::get(split_obj)) {
0073 return range_split_object_provider<Range>::get(split_obj);
0074 }
0075
0076 template <typename Range>
0077 using range_iterator_type = decltype(std::begin(std::declval<Range&>()));
0078
0079 #if __TBB_CPP20_CONCEPTS_PRESENT
0080 template <typename Iterator>
0081 using iterator_reference_type = typename std::iterator_traits<Iterator>::reference;
0082
0083 template <typename Range>
0084 using range_reference_type = iterator_reference_type<range_iterator_type<Range>>;
0085
0086 template <typename Value>
0087 concept blocked_range_value = std::copyable<Value> &&
0088 requires( const std::remove_reference_t<Value>& lhs, const std::remove_reference_t<Value>& rhs ) {
0089 { lhs < rhs } -> relaxed_convertible_to<bool>;
0090 { lhs - rhs } -> std::convertible_to<std::size_t>;
0091 { lhs + (rhs - lhs) } -> std::convertible_to<Value>;
0092 };
0093
0094 template <typename T>
0095 concept splittable = std::constructible_from<T, T&, tbb::detail::split>;
0096
0097 template <typename Range>
0098 concept tbb_range = std::copy_constructible<Range> &&
0099 splittable<Range> &&
0100 requires( const std::remove_reference_t<Range>& range ) {
0101 { range.empty() } -> relaxed_convertible_to<bool>;
0102 { range.is_divisible() } -> relaxed_convertible_to<bool>;
0103 };
0104
0105 template <typename Iterator>
0106 constexpr bool iterator_concept_helper( std::input_iterator_tag ) {
0107 return std::input_iterator<Iterator>;
0108 }
0109
0110 template <typename Iterator>
0111 constexpr bool iterator_concept_helper( std::random_access_iterator_tag ) {
0112 return std::random_access_iterator<Iterator>;
0113 }
0114
0115 template <typename Iterator, typename IteratorTag>
0116 concept iterator_satisfies = requires (IteratorTag tag) {
0117 requires iterator_concept_helper<Iterator>(tag);
0118 };
0119
0120 template <typename Sequence, typename IteratorTag>
0121 concept container_based_sequence = requires( Sequence& seq ) {
0122 { std::begin(seq) } -> iterator_satisfies<IteratorTag>;
0123 { std::end(seq) } -> iterator_satisfies<IteratorTag>;
0124 };
0125 #endif
0126 }
0127 }
0128 }
0129
0130 #endif