Características del lenguaje mql5, sutilezas y técnicas - página 138

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

hm, interesante, realmente me gustó la idea con los campos const, const sólo se inicializará una vez

 
Igor Makanu:

hm, interesante, me gusta la idea con los campos const, const se inicializará sólo una vez

ahora puede hacer la normalización de lotes de esta manera:

También puedes declarar miembros constantes en las clases.

 
Andrey Barinov:

También puedes declarar miembros constantes en las clases.

Bueno, sí, no uso todos los modificadores correctamente aquí, por eso causó mi admiración, lo comprobé, ahora ofusqué el código, aunque sólo quería escribirlo de forma compacta ))))

#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: ¡el plegado en ME es realmente escaso! - es agotador hacer rodar la rueda del ratón aquí y allá (((
 

Mi implementación de construcción para cada uno por MQL.

Hasta ahora, sólo funciona para arrays: 1) mql-arrays normales; 2) clases de array personalizadas, que deben tener definido el operador [](int) y lafunción globalArraySize sobrecargada.

Sintaxis:

 foreach(element_var, array)  { ... }

Un array puede definirse como una variable o una expresión - por eso tuvimos que construir el jardín). La expresión se ejecuta una vez, almacenando un puntero a la matriz, y luego accediendo al puntero.


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


Ejemplos de 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:

Ejemplos de uso:

Un poco reescrito

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

Mi implementación de construcción para cada uno por MQL.

Hasta ahora, sólo funciona para arrays: 1) mql-arrays normales; 2) clases de array personalizadas, que deben tener definido el operador [](int) y la función global ArraySize sobrecargada.

¡Esto es genial! ¿Es posible hacer una variante de este tipo?

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:

¡Esto es genial! ¿Es posible hacer una versión de esto?

Bueno, inicializar un array con variables no está soportado en MQL. Puedes hacer una asignación a un elemento del array:

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

 
Alexey Navoykov:
Bueno, inicializar un array con variables no está soportado en MQL. Puedes hacer una asignación a un elemento del array:

No he averiguado la implementación, pero no veo el sentido de hacerlo así.


Esto no funciona

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

Esta variante no funciona

Sí, lo es. Cuando empecé a investigar, descubrí una interesante peculiaridad. Cuando un argumento de un tipo constante(const int, por ejemplo) se pasa a una plantilla, se toma simplemente como: T = int, pero la constancia se tiene en cuenta de alguna manera también, lo que es confuso:
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);
}

Al principio pensé que era una característica de MQL, pero es lo mismo en C++.

 
Alexey Navoykov:

Al principio pensé que era una característica de MQL, pero es lo mismo en C++ también.

porque el tipo es const int. es que en la plantilla se puede seguir adjuntando const al frente sin problemas

pero si en c++ se puede eliminar la const de un tipo mediante unas simples manipulaciones, no se puede hacer en mql.

Razón de la queja: