Merkmale der Sprache mql5, Feinheiten und Techniken - Seite 138

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

hm, interessant, wirklich mochte die Idee mit const Felder, const wird nur einmal initialisiert werden

 
Igor Makanu:

hm, interessant, ich mag die Idee mit const Felder, const wird nur einmal initialisiert werden

Sie können jetzt auf diese Weise eine Losnormalisierung durchführen:

Sie können konstante Mitglieder auch in Klassen deklarieren.

 
Andrey Barinov:

Sie können auch konstante Mitglieder in Klassen deklarieren.

Nun, ja, ich verwende hier nicht alle Modifikatoren richtig, deshalb hat es meine Bewunderung hervorgerufen, ich habe es überprüft, jetzt habe ich den Code verschleiert, obwohl ich ihn nur kompakt schreiben wollte ))))

#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: Die Faltung in ME ist wirklich mangelhaft! - es ist ermüdend, das Mausrad hin und her zu drehen (((
 

Meine Implementierung von construct for each von MQL.

Bisher funktioniert es nur für Arrays: 1) reguläre mql-Arrays; 2) benutzerdefinierte Array-Klassen, die [](int)-Operator definiert und globaleArraySize-Funktion überladen haben sollte.

Syntax:

 foreach(element_var, array)  { ... }

Ein Array kann entweder als Variable oder als Ausdruck definiert werden - deshalb mussten wir den Garten bauen). Der Ausdruck wird einmal ausgeführt, wobei ein Zeiger auf das Array gespeichert und dann auf den Zeiger zugegriffen wird.


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


Beispiele für den Gebrauch:

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:

Beispiele für die Verwendung:

Ein wenig umgeschrieben

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

Meine Implementierung von construct for each von MQL.

Bisher funktioniert es nur für Arrays: 1) reguläre mql-Arrays; 2) benutzerdefinierte Array-Klassen, die [](int)-Operator definiert und globale ArraySize-Funktion überladen haben sollte.

Das ist cool! Ist es möglich, eine solche Variante zu erstellen?

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:

Das ist cool! Ist es möglich, eine Version davon zu erstellen?

Nun, die Initialisierung eines Arrays mit Variablen wird in MQL nicht unterstützt. Sie können eine Zuweisung an ein Arrayelement vornehmen:

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

 
Alexey Navoykov:
Nun, die Initialisierung eines Arrays mit Variablen wird in MQL nicht unterstützt. Sie können eine Zuweisung an ein Arrayelement vornehmen :

Ich habe noch nicht herausgefunden, wie die Umsetzung erfolgt, aber ich sehe keinen Sinn darin, es auf diese Weise zu tun.


Das funktioniert nicht

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

Diese Variante funktioniert nicht

Ja, das ist sie. Als ich begann, mich damit zu befassen, entdeckte ich eine interessante Besonderheit. Wenn ein Argument eines konstanten Typs( z. B.const int) an eine Schablone übergeben wird, wird es einfach als: T = int aufgefasst, aber die Konstante wird auch irgendwie berücksichtigt, was verwirrend ist:
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);
}

Zuerst dachte ich, es sei eine Funktion von MQL, aber es ist dasselbe in C++.

 
Alexey Navoykov:

Zuerst dachte ich, es sei eine Funktion von MQL, aber es ist auch in C++ so.

weil der Typ const int ist. Es ist nur so, dass man in der Vorlage ohne Probleme const an den Anfang setzen kann

aber wenn man in C++ const von einem Typ durch einige einfache Manipulationen entfernen kann, kann man das in Mql nicht tun.