Mql5 dilinin özellikleri, incelikleri ve çalışma yöntemleri - sayfa 138

 
fxsaber :
 // Некоторые возможности структур, которых нет у классов.

hmm, ilginç, const alanlarıyla ilgili fikri gerçekten beğendim, const yalnızca bir kez başlatılacak

 
Igor Makanu :

hmm, ilginç, const alanlarıyla ilgili fikri gerçekten beğendim, const yalnızca bir kez başlatılacak

şimdi çok şeyi şu şekilde normalleştirebilirsiniz:

Ayrıca sınıflarda sabit üyeler de bildirebilirsiniz.

 
Andrey Barinov :

Ayrıca sınıflarda sabit üyeler de bildirebilirsiniz.

evet, burada genel olarak tüm değiştiricileri gerçekten kullanmıyorum, bu yüzden hayranlığımı uyandırdı, kontrol ettim, şimdi kodu karıştırdım, ancak kompakt bir şekilde yazmak istedim)))

 #property strict
//+------------------------------------------------------------------+
class NL
  {
#ifndef SID #define SID(v) SymbolInfoDouble ( _Symbol ,v)
private : const class sl
     {
   public : double      s,b,l; int d;sl():s(SID( SYMBOL_VOLUME_STEP )),b(SID( SYMBOL_VOLUME_MAX )),l(SID( SYMBOL_VOLUME_MIN )){; long i= 10000000 ,k= long (s/ 0.0000001 );d= 0 ; while (d< 7 && k%i> 0 ){i/= 10 ;d++;}} #endif
     }
   param; public :   double Lot( double value){ return ( NormalizeDouble ( fmax ( fmin (param.s* round (value/param.s),param.b),param.l),param.d));}
  }
Normalize;
//+------------------------------------------------------------------+
void OnStart ()
  {
   double l = 0.0 ;
   for ( int i= 0 ;i< 10 ;i++)
     {
      l+= 0.005 ;
       Print (Normalize.Lot(l));
     }
  }
//+------------------------------------------------------------------+
Not: ME'de katlamak yeterli değil! - bir oraya bir buraya dönmek için fare tekerleğini zorlar (((
 

MQL kullanarak her yapı için uygulamam.

Şimdiye kadar sadece diziler için çalışıyor: 1) standart mql-dizileri; 2) [](int) operatörünün ve ayrıca aşırı yüklenmiş genel ArraySize işlevinin tanımlı olması gereken kullanıcı tanımlı dizi sınıfları.

Sözdizimi:

 foreach(element_var, array)  { ... }

Bir dizi hem bir değişken hem de bir ifade ile ayarlanabilir - bu nedenle bahçeyi çitle çevirmek zorunda kaldık) İfade bir kez yürütülür, işaretçi diziye kaydedilir ve ardından erişim bu işaretçi tarafından yapılır.


 #define TEMPL(T) template < typename T>


enum E_TRUE  { __TRUE= 1 };
enum E_FALSE { __FALSE= 0 };

TEMPL(T) E_TRUE  __IsMqlArray(T&[], int ) { return true ; }
TEMPL(T) E_FALSE __IsMqlArray(T&, int )   { return false ; }
TEMPL(T) E_FALSE __IsMqlArray(T, uint )   { return false ; }

#define IS_MQL_ARRAY(var)  ( typename (__IsMqlArray(var, 0 ))== typename (E_TRUE) )


static
class __CForeachHelper
{
 public :
  TEMPL(T)
   class __CDummyArr { public : T data[]; };
  TEMPL(T)
   struct __TValue { public :  T data;  __TValue(T value) { data= value; } };
   
  TEMPL(T) T*    Ptr(T* a) { return a; }
  TEMPL(T) T*    Ptr(T& a) { return &a; }
  TEMPL(T) __CDummyArr<T>* Ptr( const T&[])  { return NULL ; }
  
  TEMPL(T) __TValue<T>     Obj( const void * p, T)               { return (T)p; }
  TEMPL(T) __CDummyArr<T>* Obj( const void * p, __CDummyArr<T>*) { return (__CDummyArr<T>*)p; }
}
__foreachhelper;


#define __ARR_ITEM(ptr, array, i)  (IS_MQL_ARRAY(array) ? array[i] : __foreachhelper.Obj(ptr,   0 ?__foreachhelper.Ptr(array) : NULL ).data[i])

#define __ARR_SIZE(ptr, array) (IS_MQL_ARRAY(array) ? ArraySize (array) : ArraySize (__foreachhelper.Obj(ptr,   0 ?__foreachhelper.Ptr(array) : NULL ).data))


#define CONCAT(a, b) a ##b

#define CONCAT2(a, b) CONCAT(a, b)


#define __FORVAR(var) CONCAT2(__for ##var, __LINE__ )


#define foreach(element, array) \
   if ( 0 ) { class __CForeachArrCheck \ // Проверка наличия конструктора у элемента mql-массива
           { public : TEMPL(T) void f(T&){}  TEMPL(T) void f(T*){}  TEMPL(T) void f(T* const &[]){}  TEMPL(T) void f(T const &[]) { T arr[ 1 ]; } \           
           } _fcheck;  _fcheck.f(array); \
         } \
   else \
   for ( int __FORVAR(state)= 1 ;  __FORVAR(state)== 1 ; ) \
   for ( const void * __FORVAR(ptr)=__foreachhelper.Ptr(array);  __FORVAR(state)== 1 ; ) \
     for ( int __FORVAR(i)= 0 , __FORVAR(count)=__ARR_SIZE(__FORVAR(ptr), array);  __FORVAR(state)--== 1 && __FORVAR(i)<__FORVAR(count);  __FORVAR(i)++) \
       for (element=__ARR_ITEM(__FORVAR(ptr), array, __FORVAR(i));  __FORVAR(state)== 0 ;  __FORVAR(state)= 1 )


Kullanım örnekleri:

 template < typename T>
class CArr
{ 
 public : 
  T data[];
  T     operator []( int i)   const { return data[i]; }
   void operator =(T const &arr[]) { int size= ArraySize (arr);   ArrayResize (data, size);   for ( int i= 0 ; i<size; i++) data[i]=arr[i]; }
};


template < typename T>
int ArraySize ( const CArr<T> &arr) { return ArraySize (arr.data); }


class A { public : double value;  A( double val= 0 ) { value=val; } };


CArr< int >* GetArr() { Print ( "Get Array" );   static int arr[]={ 10 , 20 , 30 };   static CArr< int > Arr= arr;   return &Arr; }


void OnStart ()
{
   Print ( "Test 1" );
   double arr[]= { 10 , 20 , 30 };
            
  foreach( double val, arr) Print (val);
       
   Print ( "Test 2" );
  CArr< double > arr2 = arr;
       
  foreach( double val, arr2) Print (val);

         
   Print ( "Test 3" );
  A _a( 10 ), _b( 20 ), _c( 30 );
  A* arr3[ 3 ];
  arr3[ 0 ]=&_a;  arr3[ 1 ]=&_b;  arr3[ 2 ]=&_c;
       
  foreach(A* a, arr3) Print (a.value);

   Print ( "Test 4" );
  CArr<A*> arr4 = arr3;

  foreach(A* a, arr4) Print (a.value);


   Print ( "Test 5" );

  foreach( int a, GetArr()) Print (a);
}
 
Alexey Navoykov :

Kullanım örnekleri:

biraz yeniden yazdım

   //void operator=(T const &arr[]) { int size=ArraySize(arr);  ArrayResize(data, size);  for (int i=0; i<size; i++) data[i]=arr[i]; }
   void operator =(T const &arr[]) { ArrayResize (data, ArrayCopy (data, arr)); }
 
Alexey Navoykov :

MQL kullanarak her yapı için uygulamam.

Şimdiye kadar sadece diziler için çalışıyor: 1) standart mql-dizileri; 2) [](int) operatörünün yanı sıra aşırı yüklenmiş genel işlev ArraySize tanımlı olması gereken kullanıcı tanımlı dizi sınıfları.

Harika çıktı! Böyle bir seçenek yapmak mümkün mü?

 void OnStart ()
{
   MqlTick Ticks[ 3 ];
  
   for ( int i = 0 ; i < ArraySize (Ticks); i++)
    Ticks[i].bid = i + 1 ;

  foreach( MqlTick Tick, Ticks) Print (Tick.bid); // OK
    
  foreach( MqlTick Tick[ 1 ], Ticks) ArrayPrint (Tick); // 'Tick' - invalid array access   
}
 
fxsaber :

Harika çıktı! Böyle bir seçenek yapmak mümkün mü?

Bir diziyi değişkenlerle başlatmak MQL'de desteklenmez. Bir dizi öğesine atayabilirsiniz:

foreach(Ticks[0], Ticks) ArrayPrint (Ticks[0].bid);

 
Alexey Navoykov :
Bir diziyi değişkenlerle başlatmak MQL'de desteklenmez. Bir dizi öğesine atayabilirsiniz :

Uygulamayı çözemedim, ancak bunu yaparken bir anlam görmüyorum.


Bu seçenek çalışmıyor.

 void f( const int &Array[] )
{
   foreach ( int val, Array) Print(val);
}
 
fxsaber :

Bu seçenek çalışmıyor.

Evet kesinlikle. Anlamaya başlayarak, ilginç bir özellik keşfettim. Şablonun içindeki şablona (örneğin, const int ) bir sabit tür argümanı iletirken, basitçe şu şekilde algılanır: T = int, ancak, bir şekilde sabitlik de dikkate alınır, bu kafa karıştırıcıdır:
 template < typename T>
class B { };

template < typename T>
void f(T & a)
{ 
  B< const T> b;     // OK. Значит T==int
  const T arr[]={}; // Тоже всё ОК.
  T arr2[];         // 'arr2' - 'const' variable must be initialized.  wtf?
} 

void OnStart ()
{
   const int a= 0 ;
  f(a);
}

İlk başta bunun MQL'nin bir özelliği olduğunu düşündüm, ancak C++'da da aynı.

 
Alexey Navoykov :

İlk başta bunun MQL'nin bir özelliği olduğunu düşündüm ama C++'da da aynı.

çünkü tür const int. sadece şablonda, herhangi bir sorun olmadan önüne const ekleyebilirsiniz.

ancak eğer c++'da basit manipülasyonlarla bir türden const'ı kaldırmak mümkünse, mql'de bu yapılamaz