Caratteristiche del linguaggio mql5, sottigliezze e tecniche - pagina 138

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

hm, interessante, mi piaceva molto l'idea dei campi const, const sarà inizializzato solo una volta

 
Igor Makanu:

hm, interessante, mi piace l'idea con campi const, const sarà inizializzato solo una volta

potete ora fare la normalizzazione dei lotti in questo modo:

Si possono dichiarare membri costanti anche nelle classi.

 
Andrey Barinov:

Potete anche dichiarare membri costanti nelle classi.

Beh, sì, non uso correttamente tutti i modificatori qui, ecco perché ha causato la mia ammirazione, l'ho controllato, ora ho offuscato il codice, anche se volevo solo scriverlo in modo compatto ))))

#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));
     }
  }
//+------------------------------------------------------------------+
ZS: la piegatura in ME è davvero carente! - è faticoso far rotolare la rotella del mouse qua e là (((
 

La mia implementazione del costrutto per ogni MQL.

Finora, funziona solo per gli array: 1) i regolari mql-arrays; 2) le classi di array personalizzate, che dovrebbero avere l'operatore [](int) definito e lafunzione globaleArraySize sovraccaricata.

Sintassi:

 foreach(element_var, array)  { ... }

Un array può essere definito come una variabile o un'espressione - ecco perché abbiamo dovuto costruire il giardino). L'espressione viene eseguita una volta, memorizzando un puntatore all'array, e poi accedendo al puntatore.


#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)


Esempi d'uso:

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:

Esempi di utilizzo:

Un po' riscritto

  //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:

La mia implementazione del costrutto per ogni MQL.

Finora, funziona solo per gli array: 1) i regolari mql-arrays; 2) le classi di array personalizzate, che dovrebbero avere l'operatore [](int) definito e la funzione globale ArraySize sovraccaricata.

Che figata! È possibile fare una tale variante?

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:

Che figata! È possibile fare una versione di questo?

Beh, l'inizializzazione di un array con variabili non è supportata in MQL. È possibile effettuare un'assegnazione a un elemento dell'array:

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

 
Alexey Navoykov:
Beh, l'inizializzazione di una matrice con variabili non è supportata in MQL. Puoi fare un'assegnazione a un elemento della matrice:

Non capisco l'implementazione, ma non vedo il senso di farlo in questo modo.


Questo non funziona

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

Questa variante non funziona

Sì, è così. Quando ho iniziato a indagare, ho scoperto una particolarità interessante. Quando un argomento di tipo costante(const int, per esempio) viene passato a un template, viene preso semplicemente come: T = int, ma anche la costanza viene in qualche modo presa in considerazione, il che confonde:
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);
}

All'inizio pensavo fosse una caratteristica di MQL, ma è lo stesso in C++.

 
Alexey Navoykov:

All'inizio pensavo fosse una caratteristica di MQL, ma è lo stesso anche in C++.

perché il tipo è const int. è solo che nel template si può ancora attaccare const davanti senza problemi

ma se in c++ potete rimuovere const da un tipo con alcune semplici manipolazioni, non potete farlo in mql.

Motivazione: