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>
12namespace System {
namespace Details {
16template<
typename Enumerable>
17using EnumeratorOf = std::remove_reference_t<decltype(*(std::declval<Enumerable>().GetEnumerator()))>;
21template<
typename Enumerable>
22using ValueTypeOfEnumerable =
decltype(std::declval<EnumeratorOf<Enumerable>>().get_Current());
24template<
typename Enumerator>
25using ValueTypeOfEnumerator =
decltype(std::declval<Enumerator>().get_Current());
30template <
typename T,
typename =
void>
31struct IsIterable : std::false_type {};
33struct IsIterable<
T, decltype(std::declval<T>().begin(), std::declval<T>().end(), void())>
39using IterableValueType =
decltype(*(std::declval<T>().begin()));
44template<
typename T,
typename =
void>
45struct ReturnTypeTrait {};
49struct ReturnTypeTrait<
T, std::enable_if_t<IsSmartPtr<T>::value>>
51 using Pointee = std::remove_reference_t<decltype(*(std::declval<T>()))>;
52 using ReturnType = SmartPtr<Pointee>;
53 static constexpr bool value =
true;
58struct ReturnTypeTrait<
T, std::enable_if_t<!IsSmartPtr<T>::value && IsBoxable<T>::value>>
62 static constexpr bool value =
false;
67struct ReturnTypeTrait<
T, std::enable_if_t<!IsSmartPtr<T>::value && !IsBoxable<T>::value>>
70 using ReturnType = SmartPtr<Pointee>;
71 static constexpr bool value =
true;
78template<
typename D,
typename S>
79using WithoutCast = std::integral_constant<bool, std::is_same<typename ReturnTypeTrait<D>::ReturnType,
typename ReturnTypeTrait<S>::ReturnType>::value>;
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>;
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>;
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>;
106template<
typename T,
typename Enumerator>
107struct WrappingIterator
109 using TargetType =
T;
110 using SourceType = ValueTypeOfEnumerator<Enumerator>;
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&;
118 WrappingIterator() : mIsEnd(true) {}
119 WrappingIterator(SmartPtr<Enumerator> enumerator)
120 : mEnumerator(std::move(enumerator))
121 , mIsEnd(!mEnumerator->MoveNext())
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;
130 bool operator!=(
const WrappingIterator& other)
const
132 if (mIsEnd && other.mIsEnd)
return false;
134 if (mIsEnd || other.mIsEnd)
return true;
142 template<
typename Q = TargetType>
143 std::enable_if_t<WithoutCast<Q, SourceType>::value, MakeConstRef_t<SourceType>>
146 return mEnumerator->get_Current();
149 template<
typename Q = TargetType>
150 std::enable_if_t<WithDynamicCast<Q, SourceType>::value, value_type>
153 return System::ExplicitCast<typename ReturnTypeTrait<Q>::Pointee>(mEnumerator->get_Current());
156 template<
typename Q = TargetType>
157 std::enable_if_t<WithUnboxing<Q, SourceType>::value, value_type>
160 return ObjectExt::Unbox<typename ReturnTypeTrait<Q>::ReturnType>(mEnumerator->get_Current());
163 template<
typename Q = TargetType>
164 std::enable_if_t<WithBoxing<Q, SourceType>::value, value_type>
170 WrappingIterator& operator++()
172 mIsEnd = ! mEnumerator->MoveNext();
178 SmartPtr<Enumerator> mEnumerator;
189template<
typename Enumerable,
typename T = ValueTypeOfEnumerable<Enumerable>,
typename Payload = SmartPtr<Enumerable>>
190struct EnumeratorAdapter
192 using iterator = WrappingIterator<T, EnumeratorOf<Enumerable>>;
194 EnumeratorAdapter(Payload enumerable) : mEnumerable(std::move(enumerable)) {}
198 return WrappingIterator<T, EnumeratorOf<Enumerable>>(mEnumerable->GetEnumerator());
214template<
typename T,
typename Iterator>
215struct AdaptedIterator
217 using TargetType =
T;
218 using SourceType =
typename std::iterator_traits<Iterator>::value_type;
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&;
226 AdaptedIterator(Iterator origin_iterator)
227 : mOriginIterator(std::move(origin_iterator))
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;
237 friend bool operator==(
const AdaptedIterator& lhs,
const AdaptedIterator& rhs)
239 return lhs.mOriginIterator == rhs.mOriginIterator;
242 friend bool operator!=(
const AdaptedIterator& lhs,
const AdaptedIterator& rhs)
244 return lhs.mOriginIterator != rhs.mOriginIterator;
247 template<
typename Q = TargetType>
248 std::enable_if_t<WithoutCast<Q, SourceType>::value, MakeConstRef_t<value_type>>
251 return *mOriginIterator;
254 template<
typename Q = TargetType>
255 std::enable_if_t<WithDynamicCast<Q, SourceType>::value, value_type>
258 const SourceType &value = *mOriginIterator;
259 return System::ExplicitCast<typename ReturnTypeTrait<Q>::Pointee>(value);
262 template<
typename Q = TargetType>
263 std::enable_if_t<WithUnboxing<Q, SourceType>::value, value_type>
266 const SourceType &value = *mOriginIterator;
267 return ObjectExt::Unbox<typename ReturnTypeTrait<Q>::ReturnType>(value);
270 template<
typename Q = TargetType>
271 std::enable_if_t<WithBoxing<Q, SourceType>::value, value_type>
274 const SourceType &value = *mOriginIterator;
278 AdaptedIterator& operator++()
285 Iterator mOriginIterator;
291template<
typename Iterable,
typename T>
292struct CppIteratorAdapter
294 CppIteratorAdapter(SmartPtr<Iterable> enumerable) : mEnumerable(std::move(enumerable)) {}
296 using origin_iterator =
decltype(std::declval<Iterable>().begin());
297 using iterator = AdaptedIterator<T, origin_iterator>;
301 return iterator(mEnumerable->begin());
306 return iterator(mEnumerable->end());
310 SmartPtr<Iterable> mEnumerable;
320template<
typename T,
typename Enumerable>
321std::enable_if_t<!Details::IsIterable<Enumerable>::value, Details::EnumeratorAdapter<Enumerable, T>>
324 return Details::EnumeratorAdapter<Enumerable, T>(std::move(enumerable));
333template<
typename Enumerable>
334std::enable_if_t<!Details::IsIterable<Enumerable>::value, Details::EnumeratorAdapter<Enumerable>>
337 return Details::EnumeratorAdapter<Enumerable>(std::move(enumerable));
344template<
typename Enumerable>
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>>
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>>
370 return Details::CppIteratorAdapter<Enumerable, T>(std::move(enumerable));
376template<
typename Enumerable>
377std::enable_if_t<!IsSmartPtr<Enumerable>::value, Details::EnumeratorAdapter<Enumerable, Details::ValueTypeOfEnumerable<Enumerable>, Enumerable*>>
380 return Details::EnumeratorAdapter<Enumerable, Details::ValueTypeOfEnumerable<Enumerable>, Enumerable*>(
const_cast<Enumerable*
>(enumerable));
388template<
typename T,
typename Enumerable>
389std::enable_if_t<!IsSmartPtr<Enumerable>::value, Details::EnumeratorAdapter<Enumerable, T, Enumerable*>>
392 return Details::EnumeratorAdapter<Enumerable, T, Enumerable*>(
const_cast<Enumerable*
>(enumerable));
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