File indexing completed on 2025-09-17 09:14:32
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef ROOT_RRangeCast
0015 #define ROOT_RRangeCast
0016
0017 #include "ROOT/RSpan.hxx"
0018
0019 #include <cassert>
0020 #include <iterator>
0021 #include <type_traits>
0022 #include <utility>
0023
0024 namespace ROOT {
0025 namespace Internal {
0026
0027 template <typename T>
0028 struct RBaseType {
0029 using type = typename std::remove_pointer<typename std::decay<T>::type>::type;
0030 };
0031
0032
0033 template <typename T>
0034 constexpr auto hasBeginEnd(int) -> decltype(std::begin(std::declval<T>()), std::end(std::declval<T>()), true)
0035 {
0036 return true;
0037 }
0038
0039 template <typename>
0040 constexpr bool hasBeginEnd(...)
0041 {
0042 return false;
0043 }
0044
0045 template <typename T, typename WrappedIterator_t, bool isDynamic>
0046 class TypedIter {
0047
0048 public:
0049 TypedIter(WrappedIterator_t const &iter) : fIter{iter} {}
0050
0051 TypedIter &operator++()
0052 {
0053 ++fIter;
0054 return *this;
0055 }
0056 TypedIter operator++(int)
0057 {
0058 TypedIter tmp(*this);
0059 operator++();
0060 return tmp;
0061 }
0062 bool operator==(const TypedIter &rhs) const { return fIter == rhs.fIter; }
0063 bool operator!=(const TypedIter &rhs) const { return fIter != rhs.fIter; }
0064
0065 void swap(TypedIter &other) { fIter.swap(other.fIter); }
0066
0067
0068
0069
0070 T operator*()
0071 {
0072 if constexpr (isDynamic) {
0073 return dynamic_cast<T>(*fIter);
0074 } else {
0075 if constexpr (std::is_polymorphic<RBaseType<T>>::value) {
0076 assert(dynamic_cast<T>(*fIter));
0077 }
0078 return static_cast<T>(*fIter);
0079 }
0080 }
0081
0082 private:
0083 WrappedIterator_t fIter;
0084 };
0085
0086 }
0087
0088
0089
0090
0091
0092
0093 template <typename T, bool isDynamic, typename Range_t>
0094 class RRangeCast {
0095
0096 public:
0097 RRangeCast(Range_t &&inputRange) : fInputRange{inputRange}
0098 {
0099 static_assert(ROOT::Internal::hasBeginEnd<Range_t>(0),
0100 "Type with no `begin` or `end` method passed to `RRangeCast`");
0101 }
0102
0103 using const_iterator = Internal::TypedIter<T, decltype(std::cbegin(std::declval<Range_t>())), isDynamic>;
0104 const_iterator begin() const { return std::cbegin(fInputRange); }
0105 const_iterator end() const { return std::cend(fInputRange); }
0106
0107 using iterator = Internal::TypedIter<T, decltype(std::begin(std::declval<Range_t>())), isDynamic>;
0108 iterator begin() { return std::begin(fInputRange); }
0109 iterator end() { return std::end(fInputRange); }
0110
0111 private:
0112 Range_t fInputRange;
0113 };
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136 template <typename T, typename Range_t>
0137 RRangeCast<T, false, Range_t> RangeStaticCast(Range_t &&coll)
0138 {
0139 return std::forward<Range_t>(coll);
0140 }
0141
0142
0143
0144 template <typename T, typename U, std::size_t N>
0145 RRangeCast<T, false, std::span<U>> RangeStaticCast(U (&arr)[N])
0146 {
0147 return std::span<U>(arr, arr + N);
0148 }
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175 template <typename T, typename Range_t>
0176 RRangeCast<T, true, Range_t> RangeDynCast(Range_t &&coll)
0177 {
0178 return std::forward<Range_t>(coll);
0179 }
0180
0181
0182
0183 template <typename T, typename U, std::size_t N>
0184 RRangeCast<T, true, std::span<U>> RangeDynCast(U (&arr)[N])
0185 {
0186 return std::span<U>(arr, arr + N);
0187 }
0188
0189 }
0190
0191 #endif