Caractéristiques du langage mql5, subtilités et techniques - page 138

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

hm, intéressant, j'ai vraiment aimé l'idée des champs const, les const ne seront initialisés qu'une fois

 
Igor Makanu:

hm, intéressant, j'aime l'idée avec les champs const, les const ne seront initialisés qu'une fois

vous pouvez maintenant faire la normalisation des lots de cette manière :

Vous pouvez également déclarer des membres constants dans les classes.

 
Andrey Barinov:

Vous pouvez également déclarer des membres constants dans les classes.

Eh bien, oui, je n'utilise pas tous les modificateurs correctement ici, c'est pourquoi cela a provoqué mon admiration, je l'ai vérifié, maintenant j'ai obscurci le code, alors que je voulais juste l'écrire de manière compacte )))).

#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 : le pliage en ME fait vraiment défaut ! - c'est fatiguant de faire rouler la molette de la souris ici et là ((()
 

Ma mise en œuvre de la construction pour chacun par MQL.

Jusqu'à présent, cela ne fonctionne que pour les tableaux : 1) les tableaux mql-arrays ordinaires ; 2) les classes de tableaux personnalisées, qui devraient avoir l'opérateur [](int) défini et lafonction globaleArraySize surchargée.

Syntaxe :

 foreach(element_var, array)  { ... }

Un tableau peut être défini comme une variable ou une expression - c'est pourquoi nous avons dû construire le jardin). L'expression est exécutée une fois, en stockant un pointeur vers le tableau, puis en accédant au pointeur.


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


Exemples d'utilisation :

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:

Exemples d'utilisation :

Un peu de réécriture

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

Ma mise en œuvre de la construction pour chacun par MQL.

Jusqu'à présent, cela ne fonctionne que pour les tableaux : 1) les tableaux mql-arrays ordinaires ; 2) les classes de tableaux personnalisées, qui devraient avoir l'opérateur [](int) défini et la fonction globale ArraySize surchargée.

C'est cool ! Est-il possible de réaliser une telle 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:

C'est cool ! Est-il possible d'en faire une version ?

Eh bien, l'initialisation d'un tableau avec des variables n'est pas supportée dans MQL. Vous pouvez faire une affectation à un élément de tableau:

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

 
Alexey Navoykov:
Eh bien, l'initialisation d'un tableau avec des variables n'est pas supportée dans MQL. Vous pouvez faire une affectation à un élément de tableau:

Je ne comprends pas la mise en œuvre, mais je ne vois pas l'intérêt de procéder de cette façon.


Cela ne fonctionne pas

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

Cette variante ne fonctionne pas

Oui, c'est vrai. Lorsque j'ai commencé à m'y intéresser, j'ai découvert une particularité intéressante. Lorsqu'un argument d'un type constant(const int, par exemple) est transmis à un modèle, il est pris simplement comme : T = int, mais la constance est en quelque sorte prise en compte aussi, ce qui est déroutant :
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);
}

Au début, je pensais que c'était une caractéristique de MQL, mais c'est la même chose en C++.

 
Alexey Navoykov:

Au début, je pensais que c'était une caractéristique de MQL, mais c'est la même chose en C++.

parce que le type est const int. c'est juste que dans le modèle vous pouvez toujours attacher const à l'avant sans aucun problème.

mais si en c++ on peut enlever const d'un type par quelques manipulations simples, on ne peut pas le faire en mql.