File indexing completed on 2025-01-30 10:22:39
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 #if (__cplusplus < 201700L)
0033
0034 template <typename T, bool isDynamic = true, bool isPolymorphic = std::is_polymorphic<RBaseType<T>>::value>
0035 struct RCast {
0036 template <typename U>
0037 static T cast(U &&u)
0038 {
0039 return dynamic_cast<T>(u);
0040 }
0041 };
0042
0043 template <typename T>
0044 struct RCast<T, false, false> {
0045 template <typename U>
0046 static T cast(U &&u)
0047 {
0048 return static_cast<T>(u);
0049 }
0050 };
0051
0052 template <typename T>
0053 struct RCast<T, false, true> {
0054 template <typename U>
0055 static T cast(U &&u)
0056 {
0057 assert(dynamic_cast<T>(u));
0058 return static_cast<T>(u);
0059 }
0060 };
0061
0062 #endif
0063
0064
0065 template <typename T>
0066 constexpr auto hasBeginEnd(int) -> decltype(std::begin(std::declval<T>()), std::end(std::declval<T>()), true)
0067 {
0068 return true;
0069 }
0070
0071 template <typename>
0072 constexpr bool hasBeginEnd(...)
0073 {
0074 return false;
0075 }
0076
0077 template <typename T, typename WrappedIterator_t, bool isDynamic>
0078 class TypedIter {
0079
0080 public:
0081 TypedIter(WrappedIterator_t const &iter) : fIter{iter} {}
0082
0083 TypedIter &operator++()
0084 {
0085 ++fIter;
0086 return *this;
0087 }
0088 TypedIter operator++(int)
0089 {
0090 TypedIter tmp(*this);
0091 operator++();
0092 return tmp;
0093 }
0094 bool operator==(const TypedIter &rhs) const { return fIter == rhs.fIter; }
0095 bool operator!=(const TypedIter &rhs) const { return fIter != rhs.fIter; }
0096
0097 void swap(TypedIter &other) { fIter.swap(other.fIter); }
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107 #if (__cplusplus < 201700L)
0108 T operator*() { return ROOT::Internal::RCast<T, isDynamic>::cast(*fIter); }
0109 #else
0110 T operator*()
0111 {
0112 if constexpr (isDynamic) {
0113 return dynamic_cast<T>(*fIter);
0114 } else {
0115 if constexpr (std::is_polymorphic<RBaseType<T>>::value) {
0116 assert(dynamic_cast<T>(*fIter));
0117 }
0118 return static_cast<T>(*fIter);
0119 }
0120 }
0121 #endif
0122
0123 private:
0124 WrappedIterator_t fIter;
0125 };
0126
0127 }
0128
0129
0130
0131
0132
0133
0134 template <typename T, bool isDynamic, typename Range_t>
0135 class RRangeCast {
0136
0137 public:
0138 RRangeCast(Range_t &&inputRange) : fInputRange{inputRange}
0139 {
0140 static_assert(ROOT::Internal::hasBeginEnd<Range_t>(0),
0141 "Type with no `begin` or `end` method passed to `RRangeCast`");
0142 }
0143
0144 using const_iterator = Internal::TypedIter<T, decltype(std::cbegin(std::declval<Range_t>())), isDynamic>;
0145 const_iterator begin() const { return std::cbegin(fInputRange); }
0146 const_iterator end() const { return std::cend(fInputRange); }
0147
0148 using iterator = Internal::TypedIter<T, decltype(std::begin(std::declval<Range_t>())), isDynamic>;
0149 iterator begin() { return std::begin(fInputRange); }
0150 iterator end() { return std::end(fInputRange); }
0151
0152 private:
0153 Range_t fInputRange;
0154 };
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177 template <typename T, typename Range_t>
0178 RRangeCast<T, false, Range_t> RangeStaticCast(Range_t &&coll)
0179 {
0180 return std::forward<Range_t>(coll);
0181 }
0182
0183
0184
0185 template <typename T, typename U, std::size_t N>
0186 RRangeCast<T, false, std::span<U>> RangeStaticCast(U (&arr)[N])
0187 {
0188 return std::span<U>(arr, arr + N);
0189 }
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216 template <typename T, typename Range_t>
0217 RRangeCast<T, true, Range_t> RangeDynCast(Range_t &&coll)
0218 {
0219 return std::forward<Range_t>(coll);
0220 }
0221
0222
0223
0224 template <typename T, typename U, std::size_t N>
0225 RRangeCast<T, true, std::span<U>> RangeDynCast(U (&arr)[N])
0226 {
0227 return std::span<U>(arr, arr + N);
0228 }
0229
0230 }
0231
0232 #endif