Merkmale der Sprache mql5, Feinheiten und Techniken - Seite 221

 
fxsaber #:

Ich bin mir nicht sicher, wie ich die Funktionalität (Unterfeld und Methode) und die Benutzerfreundlichkeit erhalten kann. Vielleicht würde diese Option Ihren Bedürfnissen entsprechen.


Anwendung.

Das ging so schnell, und jetzt funktioniert es einwandfrei, vielen Dank!


Mit Liebe nach Russland❤️! ;-)

 
Einst war es einfach, ein solches Makro in MQL5 zu schreiben.
class MqlRatestime
{
public:
  static void f( MqlRates &Value ) { Print(Value.time); }
};

class MqlTicktime
{
public:
  static void f( MqlTick &Value ) { Print(Value.time); }
};

void OnStart()
{  
  MqlRates Rates;
  MqlTick Tick;
  
  MACROS(Rates, time); // MqlRatestime::f(Rates);
  MACROS(Tick, time);  // MqlTicktime::f(Tick);
}


Ist dies in der aktuellen Version von MQL5 möglich? Ich hatte nicht genug Einfallsreichtum, um dieses Hindernis zu überwinden:

template declarations are allowed on global, namespace or class scope only
 
fxsaber #:
Einst war es einfach, ein solches Makro in MQL5 zu schreiben.


Ist dies in der aktuellen Version von MQL5 möglich? Ich hatte nicht den Einfallsreichtum, dieses Hindernis zu überwinden:

Ich verstehe die Aufgabe nicht - Sie benötigen MqlRatest Klasse (Vorlage für sie) innerhalb einer Makro-Substitution deklariert werden?
 
mktr8591 #:
Ich verstehe die Aufgabe nicht - Sie benötigen MqlRatest Klasse (Vorlage für sie) innerhalb der Makro-Substitution deklariert werden?
Es scheint mir notwendig zu sein, verschiedene Makro-Ersetzungen für Parameter unterschiedlichen Typs zu haben.
Ich verstehe nur nicht, warum man das mit Makrosubstitution statt mit Funktionsüberladung macht.
 
mktr8591 #:
Ich verstehe die Aufgabe nicht - Sie benötigen MqlRatest Klasse (seine Vorlage) innerhalb der Makro-Substitution deklariert werden?

Nein, die Klassen sind bereits deklariert. Die Kommentare geben an, welches Ergebnis Sie erhalten möchten. Die Eingabe des Makros ist ein Objekt, und die Ausgabe ist eine Klasse, die den Namen des Objekttyps enthält.

 
Sergey Gridnev #:
Es scheint mir notwendig zu sein, unterschiedliche Makro-Ersetzungen für Parameter verschiedener Typen zu haben.
Ich verstehe nur nicht, warum dies durch Makro-Substitution und nicht durch Funktionsüberladung geschehen soll.

Die Aufgabe wurde aus dieser geboren.

Forum zum Thema Handel, automatische Handelssysteme und Strategietests

Eigenheiten von mql5, Tipps und Tricks

fxsaber, 2022.02.11 15:44

ArraySortStruct_Define(MqlRates, open)
ArraySortStruct_Define(MqlRates, high)
ArraySortStruct_Define(MqlRates, time)

void OnStart()
{
  MqlRates Rates[];
  
  CopyRates(_Symbol, PERIOD_CURRENT, 0, 5, Rates); // Взяли бары
  
  Print("\nБары без сортировки - как получили.");
  ArrayPrint(Rates);
  
  Print("\nСортируем по open-цене.");
  ArraySortStruct(MqlRates, Rates, open);
  ArrayPrint(Rates);

  Print("\nСортируем по high-цене.");
  ArraySortStruct(MqlRates, Rates, high);
  ArrayPrint(Rates);

  Print("\nСортируем по времени.");
  ArraySortStruct(MqlRates, Rates, time);
  ArrayPrint(Rates);
}

Ich habe den Eingabeparameter, in dem ich den Typ angeben muss, eingefärbt. In diesem Makro erhalte ich drei Eingabeparameter. Und ich hätte gerne zwei - ohne Schrift.

 
fxsaber #:

Nein, die Klassen sind bereits deklariert. Die Kommentare geben an, welches Ergebnis Sie erhalten möchten. Die Eingabe des Makros ist ein Objekt, und die Ausgabe ist eine Klasse, die den Namen des Objekttyps enthält.

Ich weiß nicht, wie ich dieses Problem lösen kann.

Und zu ArraySortStruct mit zwei Parametern - so funktioniert es:

#define  ArraySortStruct(ARRAY, FIELD) SortOnField_##FIELD::SORT::Sort(ARRAY)

 ArraySortStruct_Define(SortOnField_, open)
ArraySortStruct_Define(SortOnField_, high)
ArraySortStruct_Define(SortOnField_, time)


void OnStart()
  {

   MqlRates Rates[];

   CopyRates(_Symbol, PERIOD_CURRENT, 0, 5, Rates); // Взяли бары

   Print("\nБары без сортировки - как получили.");
   ArrayPrint(Rates);

   Print("\nСортируем по open-цене.");
   ArraySortStruct(Rates, open);
   ArrayPrint(Rates);

   Print("\nСортируем по high-цене.");
   ArraySortStruct(Rates, high);
   ArrayPrint(Rates);

   Print("\nСортируем по времени.");
   ArraySortStruct(Rates, time);
   ArrayPrint(Rates);
  }
 
mktr8591 #:

Und zu ArraySortStruct mit zwei Parametern - so funktioniert es:

Sie haben Recht, vielen Dank! Ich habe es an einer flachen Stelle übertrieben. Ich überlasse Ihnen Ihre Variante zum Sortieren.

// Сортировка массива структур и указателей на объекты по полю.
#define  ArraySortStruct_Define(FIELD)                                            \
namespace SortOnField_##FIELD                                                    \
{                                                                                \
  class SORT                                                                     \
  {                                                                              \
  private:                                                                       \
    template <typename T>                                                        \
    static void Swap( T &Array[], const int i, const int j )                     \
    {                                                                            \
      const T Temp = Array[i];                                                   \
                                                                                 \
      Array[i] = Array[j];                                                       \
      Array[j] = Temp;                                                           \
                                                                                 \
      return;                                                                    \
    }                                                                            \
                                                                                 \
    template <typename T>                                                        \
    static int Partition( T &Array[], const int Start, const int End )           \
    {                                                                            \
      int Marker = Start;                                                        \
                                                                                 \
      for (int i = Start; i <= End; i++)                                         \
        if (Array[i].##FIELD <= Array[End].##FIELD)                              \
        {                                                                        \
          SORT::Swap(Array, i, Marker);                                          \
                                                                                 \
          Marker++;                                                              \
        }                                                                        \
                                                                                 \
       return(Marker - 1);                                                       \
    }                                                                            \
                                                                                 \
    template <typename T>                                                        \
    static void QuickSort( T &Array[], const int Start, const int End )          \
    {                                                                            \
      if (Start < End)                                                           \
      {                                                                          \
        const int Pivot = Partition(Array, Start, End);                          \
                                                                                 \
        SORT::QuickSort(Array, Start, Pivot - 1);                                \
        SORT::QuickSort(Array, Pivot + 1, End);                                  \
      }                                                                          \
                                                                                 \
      return;                                                                    \
    }                                                                            \
                                                                                 \
  public:                                                                        \
    template <typename T>                                                        \
    static void Sort( T &Array[], int Count = WHOLE_ARRAY, const int Start = 0 ) \
    {                                                                            \
      if (Count == WHOLE_ARRAY)                                                  \
        Count = ::ArraySize(Array);                                              \
                                                                                 \
      SORT::QuickSort(Array, Start, Start + Count - 1);                          \
                                                                                 \
      return;                                                                    \
    }                                                                            \
  };                                                                             \
}

#define  ArraySortStruct(ARRAY, FIELD) SortOnField_##FIELD::SORT::Sort(ARRAY)


Anwendung.

ArraySortStruct_Define(open)
ArraySortStruct_Define(high)
ArraySortStruct_Define(time)

void OnStart()
{
  MqlRates Rates[];
  
  CopyRates(_Symbol, PERIOD_CURRENT, 0, 5, Rates); // Взяли бары
  
  Print("\nБары без сортировки - как получили.");
  ArrayPrint(Rates);
  
  Print("\nСортируем по open-цене.");
  ArraySortStruct(Rates, open);
  ArrayPrint(Rates);
  
  Print("\nСортируем по high-цене.");
  ArraySortStruct(Rates, high);
  ArrayPrint(Rates);
  
  Print("\nСортируем по времени.");
  ArraySortStruct(Rates, time);
  ArrayPrint(Rates);
}


ZZY Es ist schade, dass es nicht nach Teilbereichen oder Methoden funktioniert.

 
Das mag für niemanden eine Neuigkeit sein, aber für mich ist es unerwartet.
Wenn eine DLL gleichzeitig in verschiedenen MT5-Programmen verwendet wird,
ist zu beachten, dass sie nur einmal von dem ersten Programm geladen wird, das sie verwendet.
Das heißt, die DLL-Umgebung befindet sich in einem gemeinsamen Prozess, unabhängig davon, wie oft Sie sie importieren.
Wo ist der Haken? Die in der DLL verwendeten globalen Zeiger befinden sich alle im gleichen gemeinsamen Prozessraum.
Und das ist sehr praktisch.
 
Roman #:
Vielleicht ist das für niemanden eine Neuigkeit, aber für mich ist es unerwartet.
Wenn die DLL gleichzeitig in verschiedenen Programmen (MT5,
) verwendet wird, ist zu beachten, dass sie nur einmal vom ersten Programm geladen wird, das sie verwendet.
Das heißt, der Zustand der DLL befindet sich in einem gemeinsamen Prozess, unabhängig davon, wie oft Sie sie importieren.
Wo ist der Haken? Die in der DLL verwendeten globalen Zeiger befinden sich alle im gleichen gemeinsamen Prozessraum.
Und das ist sehr praktisch.

Das ist nichts Neues, so hat es von Anfang an funktioniert.

Nur wenn die Daten größer als __atomic__ sind, sollte der Zugriff mit kritischen Abschnitten umhüllt/geschützt werden (oder mit einem Mutex zum Terminal std::thread)