Merkmale der Sprache mql5, Feinheiten und Techniken - Seite 98

 
TheXpert:

Wozu? Um ein paar Bytes Speicherplatz zu sparen? Vor allem mit double erhält man unterschiedliche Zahlen (== wird falsch sein).

Das hat keinen Sinn. Ich mag dieses Konstrukt, ich habe es noch nie gesehen.

 
fxsaber:

Das ergibt keinen Sinn. Das Design gefällt mir, ich habe es noch nie gesehen.

Ah, ok. xor ist eleganter, imho.

 
TheXpert:

Ah, ok. xor ist eleganter, imho.

Einverstanden

#define  SWAP(A, B) { A ^= B; B ^= A; A ^= B; }


SZ

#define  SWAP(A, B) A ^= (B ^= (A ^= B));


Aus Wiki.

Auf modernenCPUs ist die XOR-Technikjedoch wesentlich langsamer als die Verwendung einer temporären Variable für den Austausch. Dies ist auf die Parallelisierung der Befehlsausführung zurückzuführen. Bei der XOR-Technik hängen die Operanden aller Befehle von den Ergebnissen der vorhergehenden Befehle ab, so dass sie in streng sequentieller Reihenfolge ausgeführt werden müssen. Es wird empfohlen, die Geschwindigkeiten der beiden Alternativen auf Ihrer Zielarchitektur von Fall zu Fall zu testen.

 
Ein Alptraum.
 
fxsaber:

Von Wiki

Was geschieht, wenn die vorherige Addition/Subtraktion parallel durchgeführt wird? )

 
Taras Slobodyanik:

Was wäre, wenn sie parallel zur vorherigen Addition/Subtraktion verlaufen würden? )

Ein sequenzabhängiger Algorithmus lässt sich nicht parallelisieren.

Ein Algorithmus mit einer zeitlichen Variable ist nicht parallelisierbar.

 
Nein, nein...
 

Forum zum Thema Handel, automatisierte Handelssysteme und Testen von Handelsstrategien

Wanzen, Wanzen, Fragen

Ilyas, 2016.08.24 11:08

Das Array ("inside") speichert die zugewiesenen - unter wie vielen Elementen das Array zugewiesen ist.

Die Logik für die Arbeit mit zugewiesenem (bedingtem) Code:
ArrayResize(arr,int size,int reserve)
  {
   if(arr.allocated<size)
      if(!ArrayAllocateMemory(arr,size+reserve))  // -> arr.allocated=size+reserve;
         return(-1);
   //---
   CallConstructorsOrDestructors(arr,size);
   //---
   arr.size=size;
   return(size);
  }
 

In der Fortsetzung unserer "Trödel"-Kolumne geht es heute um das Schablonenfieber, oder wie man eine Schablone im Arsch loswird )

Oftmals ist es notwendig, eine Variable als Schablonenargument per Referenz zu übergeben, um sie zu ändern, aber die Schablonenspezifikation erlaubt es leider nicht, die Nichtkonstanz des Arguments explizit anzugeben, wie bei normalen Funktionen:

void Modify(int&) { }  // Принимает только не константы

template<typename T>
void Modify(T& a) {  } // Принимает любые аргументы

Dies kann zu Unannehmlichkeiten führen, wenn das Argument die Vorlagenkette bis zu seinem Ziel durchläuft, wo es sich als Konstante herausstellt und nicht geändert werden kann. Und dieser Fehler tritt irgendwo in den Tiefen der Bibliotheken auf. Die Feststellung, von wo aus die ursprüngliche Vorlage aufgerufen wurde, ist manchmal eine sehr schwierige Aufgabe.

template<typename T>
void f0(T& a)  { a=10; }  // 'a' - constant cannot be modified

template<typename T>
void f1(T& a)  { f0(a); }

template<typename T>
void f2(T& a)  { f1(a); }

void Source() { const int a=0;  f2(a); }

In normalen IDEs stellt dies kein Problem dar. Zum Beispiel hat VS eine vollständige Spur der Vorlage Route, so dass es genug, um an der richtigen Stelle klicken und es wird Sie direkt dorthin. Aber es ist ein Problem in MQL. Das kann für den Vorlagenersteller zu einem ständigen Problem werden.

Aber das lässt sich beheben. Zu diesem Zweck können Sie die Überladung der Vorlage verwenden:

template<typename T>
void Modify(const T&); // Фэйковый запрещённый шаблон

template<typename T>
void Modify(T& a) { a=10; }

Wenn Sie nun versuchen, die Konstante zu übergeben, wird die obere Vorlage aufgerufen. Aber das ist keine ausreichende Lösung, denn erstens tritt der Fehler nur beim Kompilieren der ausführbaren Datei auf (und in .mqh nicht), und zweitens tritt der Fehler dort auf, wo die Vorlage deklariert ist, und nicht dort, wo sie aufgerufen wird, was wir herausfinden wollen. Gehen wir also weiter.

Wenn die Vorlage eine Methode einer Klasse ist, ist alles ganz einfach: Wir platzieren die gefälschte Vorlage in einem privaten Abschnitt und erhalten einen Zugriffsfehler, wenn wir versuchen, sie aufzurufen.

Im Falle einer einfachen Funktion ist es komplizierter. In C++ kann das Problem nicht allein durch Überladen gelöst werden, wir brauchen zusätzliche Funktionalität, die in MQL fehlt. Aber hier kommt uns die mächtige Waffe von MQL - Bugs - zu Hilfe! ) In diesem Fall erweist sich einer dieser Fehler als sehr nützlich für uns )
Wir fügen unserer gefälschten Vorlage einen zusätzlichen Parameter T2 hinzu und erhalten nun beim Versuch, die falsche Vorlage aufzurufen, einen Fehler am Aufrufpunkt:

template<typename T, typename T2>
void Modify(const T&);  // Запрещаем

template<typename T>
void Modify(T& a) { a=10; }

void Source()
{ 
  int a, const b=0;
  Modify(a);  // всё ОК
  Modify(b);  // template mismatch
}

Problem gelöst. In C++ wird die untere Vorlage natürlich in beiden Fällen aufgerufen, weil es dort keinen solchen Fehler gibt.

Diese Methode kann in einem weiteren Fall nützlich sein: wenn wir die Typen der Funktionsargumente explizit kontrollieren müssen, indem wir die implizite Umwandlung deaktivieren.
Zum Beispiel sollte die Funktion nur das datetime-Argument akzeptieren und alle Arten von int's und andere Dinge unterdrücken.
Wir machen eine entsprechende Variante:

template<typename T, typename T2>
void MyFunc(T);  // Запрещаем

void MyFunc(datetime time) {  }

Wie im vorherigen Fall wird nun ein Kompilierungsfehler ausgelöst, wenn versucht wird, einen nicht aufgelösten Typ zu übergeben.

Übrigens mache ich immer ein solches Verbot für datetime. Ich denke, es war umsonst, dass die Entwickler überhaupt eine implizite Konvertierung in datetime erlaubt haben und ohne Warnungen an den Compiler (außer für long und string). Sogar eine beliebige Aufzählung kann ohne Warnungen in sie umgewandelt werden.

Es gibt auch das gegenteilige Problem: nur einen Anruf eines bestimmten Typs zu verbieten. Die Lösung wäre dieselbe:

template<typename T,typename T2>
void MyFunc(datetime);  // Запрещаем

template<typename T>
void MyFunc(T arg) {  }


Wie bereits erwähnt, wird alles innerhalb der Klasse ohne unnötige Parameter gelöst.

 
Alexey Navoykov:

In der Fortsetzung unserer Kolumne "Schwindelerregende Hände" geht es heute um das Schablonenfieber oder wie man eine Schablone am Arsch loswird)

Oftmals ist es notwendig, eine Variable als Template-Argument per Referenz zu übergeben , um sie zu ändern.

Es besteht die Notwendigkeit, einen Verweis ohne Änderung weiterzugeben - für Geschwindigkeit oder ein Objekt.

Die bestehende C++-Vorlagenspezifikation erlaubt es jedoch leider nicht, die Nichtkonstanz eines Arguments explizit zu spezifizieren, wie es bei üblichen Funktionen der Fall ist:

Und das kann zu Unannehmlichkeiten führen, wenn das Argument die Musterkette bis zu seinem Ziel hinunterläuft und sich dort als Konstante herausstellt, die nicht geändert werden kann. Und dieser Fehler tritt irgendwo in den Tiefen der Bibliotheken auf. Die Feststellung, von wo aus die ursprüngliche Vorlage aufgerufen wurde, ist manchmal eine sehr schwierige Aufgabe.

Gibt es ein reales Beispiel in MQL5, bei dem dieses Problem auftritt?

In normalen IDEs stellt dies kein Problem dar. VS zeigt z.B. die vollständige Spur der Vorlagenroute an, so dass man nur an der richtigen Stelle klicken muss, um direkt zum Ziel zu gelangen. Aber in MQL ist das ein echtes Problem. Das kann für den Vorlagenersteller zu einem ständigen Problem werden.

Aber das lässt sich beheben. Zu diesem Zweck können Sie die Überladung der Vorlage verwenden:

Wenn Sie nun versuchen, die Konstante zu übergeben, wird die obere Vorlage aufgerufen. Aber das ist keine ausreichende Lösung, denn erstens tritt der Fehler nur beim Kompilieren der ausführbaren Datei auf (und in .mqh nicht), und zweitens tritt der Fehler dort auf, wo die Vorlage deklariert ist, und nicht dort, wo sie aufgerufen wird, was wir herausfinden wollen. Gehen wir also weiter.

Wenn die Vorlage eine Methode einer Klasse ist, ist alles ganz einfach: Wir platzieren die gefälschte Vorlage in einem privaten Abschnitt und erhalten einen Zugriffsfehler, wenn wir versuchen, sie aufzurufen.

Im Falle einer normalen Funktion ist es jedoch komplizierter. Syntaktisch ist dieses Problem in C++ überhaupt nicht lösbar, soweit ich verstanden habe. Aber wir haben Glück, dass MQL nicht C++ ist - es gibt Bugs in ihm ) Und in diesem Fall können diese Bugs umgangen werden).

Wir fügen unserer gefälschten Vorlage einen zusätzlichen Parameter T2 hinzu und erhalten am Aufrufpunkt einen Fehler, wenn wir versuchen, die falsche Vorlage aufzurufen:

Problem gelöst. In C++ wird die untere Vorlage natürlich in beiden Fällen aufgerufen.

Es fehlt ein echtes Beispiel für Bequemlichkeit.

Diese Methode kann in einem weiteren Fall nützlich sein: wenn wir die Typen der Funktionsargumente explizit kontrollieren müssen, indem wir die implizite Konvertierung deaktivieren.
Zum Beispiel darf die Funktion nur das Argument datetime akzeptieren, so dass alle Arten von ints und andere Dinge ausgeschlossen sind.
Wir machen eine entsprechende Variante:

Wie im vorherigen Fall wird nun ein Kompilierungsfehler ausgelöst, wenn versucht wird, einen nicht aufgelösten Typ zu übergeben.

Sie scheint in MQL5 in vollem Umfang genutzt zu werden, sobald die Möglichkeit dazu besteht. Wenn ich es richtig verstehe, handelt es sich um eine Norm.

Übrigens verbiete ich datetime immer. Ich denke, die Entwickler hätten eine implizite Konvertierung überhaupt nicht zulassen dürfen, und das sogar ohne Warnung an den Compiler (außer bei long und string). Sogar eine beliebige Aufzählung wird ohne Warnungen in sie umgewandelt.

Es gibt auch das gegenteilige Problem: nur einen Anruf einer bestimmten Art zu verbieten. Die Lösung wäre ähnlich:

Erleben Sie den Komfort, dass sich datetime so verhält, wie es jetzt der Fall ist. Wann liegt das Problem vor?


Alles in allem ein sehr guter und nützlicher Beitrag, danke!

Grund der Beschwerde: