#ifdef __cplusplus
#include<iostream>
#include<stdio.h>
#endif
class input_iterator_tag {};
class output_iterator_tag {};
class forward_iterator_tag : public input_iterator_tag {};
class bidirectional_iterator_tag : public forward_iterator_tag {};
class random_access_iterator_tag : public bidirectional_iterator_tag {};
struct MyIterator{
public:
int index;
class iterator_category : public random_access_iterator_tag{};
MyIterator(int __index = 0):index(__index){}
bool operator!=(MyIterator &it){
return index != it.index;
}
int operator-(MyIterator &it){
return index - it.index;
};
MyIterator operator++(){
index+=1;
#ifdef __cplusplus
return *this;
#else
return this;
#endif
}
};
template <typename _InputIter>
int __distance(_InputIter &__first, _InputIter &__last, input_iterator_tag*){
int __r=0;
for (; __first != __last; ++__first)
++__r;
return __r;
}
template <typename _RandIter>
int __distance(_RandIter &__first, _RandIter &__last, forward_iterator_tag*){
return __last - __first;
}
//+------------------------------------------------------------------+
//| MQL bugs bypass |
//+------------------------------------------------------------------+
#ifdef __MQL5__
// Bypass the bug (https://www.mql5.com/ru/forum/1111/page2648#comment_15015191)
template <typename _InputIter>
int __distance(_InputIter &__first, _InputIter &__last, forward_iterator_tag* __category){
return __distance(__first, __last, (input_iterator_tag*) __category);
};
template <typename _InputIter>
int __distance(_InputIter &__first, _InputIter &__last, random_access_iterator_tag* __category){
return __distance(__first, __last, (bidirectional_iterator_tag*) __category);
};
// Bypass Compilation ERROR: '_InputIter' - struct undefined
template<typename T>
class GetStructType{
public:
struct type : public T{};
};
template <typename _InputIter>
int distance_mql(_InputIter &__first, _InputIter &__last){
//_InputIter::iterator_category category; //Compilation ERROR: '_InputIter' - struct undefined
GetStructType<_InputIter>::type::iterator_category category;
GetStructType<_InputIter>::type::iterator_category* ptr = &category;
// Bypass the bug (https://www.mql5.com/ru/forum/1111/page2648#comment_15015191)
random_access_iterator_tag* ptr_ra = dynamic_cast<random_access_iterator_tag*>(ptr);
if(ptr_ra != NULL){
return __distance(__first, __last, ptr_ra);
};
bidirectional_iterator_tag* ptr_bd = dynamic_cast<bidirectional_iterator_tag*>(ptr);
if(ptr_bd != NULL){
return __distance(__first, __last, ptr_bd);
};
forward_iterator_tag* ptr_fw = dynamic_cast<forward_iterator_tag*>(ptr);
if(ptr_fw != NULL){
return __distance(__first, __last, ptr_fw);
};
input_iterator_tag* ptr_in = dynamic_cast<input_iterator_tag*>(ptr);
if(ptr_in != NULL){
return __distance(__first, __last, ptr_in);
};
//TODO RAISE EXCEPTION
return -1;
}
void OnStart(){
MyIterator it1(1);
MyIterator it2(5);
printf("result:%d", distance_mql(it1, it2));
}
#endif
//+------------------------------------------------------------------+
//| C++ realization |
//+------------------------------------------------------------------+
#ifdef __cplusplus
template <typename _InputIter>
int distance_cplusplus(_InputIter &__first, _InputIter &__last){
return __distance(__first, __last, (typename _InputIter::iterator_category*)(NULL));
}
int main(){
MyIterator it1(1);
MyIterator it2(5);
printf("result:%d", distance_cplusplus(it1, it2));
return 0;
}
#endif