CodePorting.Translator Cs2Cpp
CodePorting.Translator.Cs2Cpp.Framework
enumerator_adapter.h
1
2#pragma once
3
4#include <system/smart_ptr.h>
5#include <system/boxable_traits.h>
6#include <system/object_ext.h>
7#include <system/make_const_ref.h>
8#include <iterator>
9#include <utility>
10#include <type_traits>
11
12namespace System { namespace Details {
13
16template<typename Enumerable>
17using EnumeratorOf = std::remove_reference_t<decltype(*(std::declval<Enumerable>().GetEnumerator()))>;
18
21template<typename Enumerable>
22using ValueTypeOfEnumerable = decltype(std::declval<EnumeratorOf<Enumerable>>().get_Current());
23
24template<typename Enumerator>
25using ValueTypeOfEnumerator = decltype(std::declval<Enumerator>().get_Current());
26
30template <typename T, typename = void>
31struct IsIterable : std::false_type {};
32template <typename T>
33struct IsIterable<T, decltype(std::declval<T>().begin(), std::declval<T>().end(), void())>
34 : std::true_type {};
35
38template<typename T>
39using IterableValueType = decltype(*(std::declval<T>().begin()));
40
44template<typename T, typename = void>
45struct ReturnTypeTrait {};
46
48template<typename T>
49struct ReturnTypeTrait<T, std::enable_if_t<IsSmartPtr<T>::value>>
50{
51 using Pointee = std::remove_reference_t<decltype(*(std::declval<T>()))>;
52 using ReturnType = SmartPtr<Pointee>;
53 static constexpr bool value = true;
54};
55
57template<typename T>
58struct ReturnTypeTrait<T, std::enable_if_t<!IsSmartPtr<T>::value && IsBoxable<T>::value>>
59{
60 using Pointee = void;
61 using ReturnType = T;
62 static constexpr bool value = false;
63};
64
66template<typename T>
67struct ReturnTypeTrait<T, std::enable_if_t<!IsSmartPtr<T>::value && !IsBoxable<T>::value>>
68{
69 using Pointee = T;
70 using ReturnType = SmartPtr<Pointee>;
71 static constexpr bool value = true;
72};
73
78template<typename D, typename S>
79using WithoutCast = std::integral_constant<bool, std::is_same<typename ReturnTypeTrait<D>::ReturnType, typename ReturnTypeTrait<S>::ReturnType>::value>;
80
85template<typename D, typename S>
86using WithDynamicCast = std::integral_constant<bool, ReturnTypeTrait<D>::value && ReturnTypeTrait<S>::value && !std::is_same<typename ReturnTypeTrait<D>::Pointee, typename ReturnTypeTrait<S>::Pointee>::value>;
87
92template<typename D, typename S>
93using WithUnboxing = std::integral_constant<bool, !ReturnTypeTrait<D>::value && ReturnTypeTrait<S>::value && std::is_same<typename ReturnTypeTrait<S>::Pointee, System::Object>::value>;
94
99template<typename D, typename S>
100using WithBoxing = std::integral_constant<bool, ReturnTypeTrait<D>::value && !ReturnTypeTrait<S>::value && std::is_same<typename ReturnTypeTrait<D>::Pointee, System::Object>::value>;
101
106template<typename T, typename Enumerator>
107struct WrappingIterator
108{
109 using TargetType = T;
110 using SourceType = ValueTypeOfEnumerator<Enumerator>;
111
112 using iterator_category = std::forward_iterator_tag;
113 using value_type = typename ReturnTypeTrait<TargetType>::ReturnType;
114 using difference_type = std::ptrdiff_t;
115 using pointer = value_type*;
116 using reference = value_type&;
117
118 WrappingIterator() : mIsEnd(true) {}
119 WrappingIterator(SmartPtr<Enumerator> enumerator)
120 : mEnumerator(std::move(enumerator))
121 , mIsEnd(!mEnumerator->MoveNext())
122 {}
123
124 WrappingIterator(const WrappingIterator& other) = default;
125 WrappingIterator(WrappingIterator&& other) noexcept = default;
126 WrappingIterator& operator=(const WrappingIterator& other) = default;
127 WrappingIterator& operator=(WrappingIterator&& other) noexcept = default;
128 ~WrappingIterator() = default;
129
130 bool operator!=(const WrappingIterator& other) const
131 {
132 if (mIsEnd && other.mIsEnd) return false;
133
134 if (mIsEnd || other.mIsEnd) return true;
135
136 // The correct comparison, but we use this iterator only for range-based loops
137 // so it doesn't matter
138 // mEnumerator->get_Current() != other.mEnumerator->get_Current();
139 return false;
140 }
141
142 template<typename Q = TargetType>
143 std::enable_if_t<WithoutCast<Q, SourceType>::value, MakeConstRef_t<SourceType>>
144 operator*() const
145 {
146 return mEnumerator->get_Current();
147 }
148
149 template<typename Q = TargetType>
150 std::enable_if_t<WithDynamicCast<Q, SourceType>::value, value_type>
151 operator*() const
152 {
153 return System::ExplicitCast<typename ReturnTypeTrait<Q>::Pointee>(mEnumerator->get_Current());
154 }
155
156 template<typename Q = TargetType>
157 std::enable_if_t<WithUnboxing<Q, SourceType>::value, value_type>
158 operator*() const
159 {
160 return ObjectExt::Unbox<typename ReturnTypeTrait<Q>::ReturnType>(mEnumerator->get_Current());
161 }
162
163 template<typename Q = TargetType>
164 std::enable_if_t<WithBoxing<Q, SourceType>::value, value_type>
165 operator*() const
166 {
167 return ObjectExt::Box(mEnumerator->get_Current());
168 }
169
170 WrappingIterator& operator++()
171 {
172 mIsEnd = ! mEnumerator->MoveNext();
173 return *this;
174 }
175
176private:
178 SmartPtr<Enumerator> mEnumerator;
180 bool mIsEnd;
181};
182
189template<typename Enumerable, typename T = ValueTypeOfEnumerable<Enumerable>, typename Payload = SmartPtr<Enumerable>>
190struct EnumeratorAdapter
191{
192 using iterator = WrappingIterator<T, EnumeratorOf<Enumerable>>;
193
194 EnumeratorAdapter(Payload enumerable) : mEnumerable(std::move(enumerable)) {}
195
196 iterator begin()
197 {
198 return WrappingIterator<T, EnumeratorOf<Enumerable>>(mEnumerable->GetEnumerator());
199 }
200
201 iterator end()
202 {
203 return iterator();
204 }
205
206private:
207 Payload mEnumerable;
208};
209
210
214template<typename T, typename Iterator>
215struct AdaptedIterator
216{
217 using TargetType = T;
218 using SourceType = typename std::iterator_traits<Iterator>::value_type;
219
220 using iterator_category = std::forward_iterator_tag;
221 using value_type = typename ReturnTypeTrait<TargetType>::ReturnType;
222 using difference_type = std::ptrdiff_t;
223 using pointer = value_type*;
224 using reference = value_type&;
225
226 AdaptedIterator(Iterator origin_iterator)
227 : mOriginIterator(std::move(origin_iterator))
228 {
229 }
230
231 AdaptedIterator(const AdaptedIterator& other) = default;
232 AdaptedIterator(AdaptedIterator&& other) noexcept = default;
233 AdaptedIterator& operator=(const AdaptedIterator& other) = default;
234 AdaptedIterator& operator=(AdaptedIterator&& other) noexcept = default;
235
236
237 friend bool operator==(const AdaptedIterator& lhs, const AdaptedIterator& rhs)
238 {
239 return lhs.mOriginIterator == rhs.mOriginIterator;
240 }
241
242 friend bool operator!=(const AdaptedIterator& lhs, const AdaptedIterator& rhs)
243 {
244 return lhs.mOriginIterator != rhs.mOriginIterator;
245 }
246
247 template<typename Q = TargetType>
248 std::enable_if_t<WithoutCast<Q, SourceType>::value, MakeConstRef_t<value_type>>
249 operator*() const
250 {
251 return *mOriginIterator;
252 }
253
254 template<typename Q = TargetType>
255 std::enable_if_t<WithDynamicCast<Q, SourceType>::value, value_type>
256 operator*() const
257 {
258 const SourceType &value = *mOriginIterator;
259 return System::ExplicitCast<typename ReturnTypeTrait<Q>::Pointee>(value);
260 }
261
262 template<typename Q = TargetType>
263 std::enable_if_t<WithUnboxing<Q, SourceType>::value, value_type>
264 operator*() const
265 {
266 const SourceType &value = *mOriginIterator;
267 return ObjectExt::Unbox<typename ReturnTypeTrait<Q>::ReturnType>(value);
268 }
269
270 template<typename Q = TargetType>
271 std::enable_if_t<WithBoxing<Q, SourceType>::value, value_type>
272 operator*() const
273 {
274 const SourceType &value = *mOriginIterator;
275 return ObjectExt::Box(value);
276 }
277
278 AdaptedIterator& operator++()
279 {
280 ++mOriginIterator;
281 return *this;
282 }
283
284private:
285 Iterator mOriginIterator;
286};
287
291template<typename Iterable, typename T>
292struct CppIteratorAdapter
293{
294 CppIteratorAdapter(SmartPtr<Iterable> enumerable) : mEnumerable(std::move(enumerable)) {}
295
296 using origin_iterator = decltype(std::declval<Iterable>().begin());
297 using iterator = AdaptedIterator<T, origin_iterator>;
298
299 iterator begin()
300 {
301 return iterator(mEnumerable->begin());
302 }
303
304 iterator end()
305 {
306 return iterator(mEnumerable->end());
307 }
308
309private:
310 SmartPtr<Iterable> mEnumerable;
311};
312
313}
314
320template<typename T, typename Enumerable>
321std::enable_if_t<!Details::IsIterable<Enumerable>::value, Details::EnumeratorAdapter<Enumerable, T>>
323{
324 return Details::EnumeratorAdapter<Enumerable, T>(std::move(enumerable));
325}
326
333template<typename Enumerable>
334std::enable_if_t<!Details::IsIterable<Enumerable>::value, Details::EnumeratorAdapter<Enumerable>>
336{
337 return Details::EnumeratorAdapter<Enumerable>(std::move(enumerable));
338}
339
344template<typename Enumerable>
345std::enable_if_t<Details::IsIterable<Enumerable>::value, System::SmartPtr<Enumerable>>
347{
348 return enumerable;
349}
350
355template<typename T, typename Enumerable>
356std::enable_if_t<Details::IsIterable<Enumerable>::value && std::is_same<typename Details::ReturnTypeTrait<T>::ReturnType, Details::IterableValueType<Enumerable>>::value, System::SmartPtr<Enumerable>>
358{
359 return enumerable;
360}
361
366template<typename T, typename Enumerable>
367std::enable_if_t<Details::IsIterable<Enumerable>::value && !std::is_same<typename Details::ReturnTypeTrait<T>::ReturnType, Details::IterableValueType<Enumerable>>::value, Details::CppIteratorAdapter<Enumerable, T>>
369{
370 return Details::CppIteratorAdapter<Enumerable, T>(std::move(enumerable));
371}
372
376template<typename Enumerable>
377std::enable_if_t<!IsSmartPtr<Enumerable>::value, Details::EnumeratorAdapter<Enumerable, Details::ValueTypeOfEnumerable<Enumerable>, Enumerable*>>
378IterateOver(const Enumerable* enumerable)
379{
380 return Details::EnumeratorAdapter<Enumerable, Details::ValueTypeOfEnumerable<Enumerable>, Enumerable*>(const_cast<Enumerable*>(enumerable));
381}
382
388template<typename T, typename Enumerable>
389std::enable_if_t<!IsSmartPtr<Enumerable>::value, Details::EnumeratorAdapter<Enumerable, T, Enumerable*>>
390IterateOver(const Enumerable* enumerable)
391{
392 return Details::EnumeratorAdapter<Enumerable, T, Enumerable*>(const_cast<Enumerable*>(enumerable));
393}
394
395}
static std::enable_if< std::is_enum< T >::value, System::SmartPtr< System::Object > >::type Box(const T &value)
Boxes value types for converting to Object. Implementation for enum types.
Definition: object_ext.h:198
Base class that enables using methods available for System.Object class in C#. All non-trivial classe...
Definition: object.h:62
Pointer class to wrap types being allocated on heap. Use it to manage memory for classes inheriting O...
Definition: smart_ptr.h:180
Definition: db_command.h:9
bool operator!=(ArraySegment< T > a, ArraySegment< T > b)
Definition: array_segment.h:157
Decimal operator*(const T &x, const Decimal &d)
Returns a new instance of Decimal class that represents a value that is a result of multiplication of...
Definition: decimal.h:556
std::enable_if_t<!Details::IsIterable< Enumerable >::value, Details::EnumeratorAdapter< Enumerable, T > > IterateOver(System::SmartPtr< Enumerable > enumerable)
This function property wraps enumerable (or iterable) object so it can be used with range-based for l...
Definition: enumerator_adapter.h:322
bool operator==(ArraySegment< T > a, ArraySegment< T > b)
Definition: array_segment.h:151