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

 
LeXpert:

Quel est l'intérêt ? économiser quelques octets de mémoire ? En particulier avec double vous obtenez des nombres différents (== sera faux).

Il n'y a aucun sens à cela. J'aime cette construction, je ne l'ai jamais vue auparavant.

 
fxsaber:

Ça n'a aucun sens. J'aime le design, je ne l'avais jamais vu auparavant.

Ah, ok. xor est plus élégant, imho.

 
LeXpert:

Ah, ok. xor est plus élégant, imho.

D'accord

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


SZ

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


De Wiki.

Toutefois, sur lesprocesseursmodernes, la technique XOR est nettement plus lente que l'utilisation d'une variable temporaire pour l'échange. Cela est dû à la parallélisation de l'exécution des instructions. Dans la technique XOR, les opérandes de toutes les commandes dépendent des résultats des commandes précédentes, elles doivent donc être exécutées dans un ordre strictement séquentiel. Il est recommandé de tester au cas par cas les vitesses des deux alternatives sur votre architecture cible.

 
Cauchemar.
 
fxsaber:

De Wiki

que se passe-t-il si l'addition/soustraction précédente est mise en parallèle ? )

 
Taras Slobodyanik:

Et s'ils mettaient en parallèle l'addition/soustraction précédente ? )

Un algorithme dépendant de la séquence ne se parallélise pas.

Un algorithme avec une variable temporelle ne l'est pas, il est donc parallélisable.

 
Non...
 

Forum sur le trading, les systèmes de trading automatisé et les tests de stratégies de trading

Bugs, bugs, questions

Ilyas, 2016.08.24 11:08

Le tableau ("inside") stocke les éléments alloués - sous combien d'éléments le tableau est alloué.

La logique de travail avec les attributions (code conditionnel) :
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);
  }
 

Dans la continuité de notre rubrique "flânerie", le sujet d'aujourd'hui est la fièvre du gabarit, ou comment se débarrasser d'un gabarit dans le cul).

Il est souvent nécessaire de passer une variable comme argument de modèle par référence pour la modifier, mais la spécification du modèle ne permet malheureusement pas de spécifier explicitement la non-constance de l'argument, comme dans les fonctions normales :

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

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

Cela peut causer des désagréments lorsque l'argument descend la chaîne de modèles jusqu'à sa destination, où il s'avère être une constante et ne peut être modifié. Et cette erreur se produit quelque part dans les profondeurs des bibliothèques. Détecter d'où le modèle original a été appelé est parfois une tâche très difficile.

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); }

Ce n'est pas un problème dans les IDE normaux. Par exemple, VS dispose d'une trace complète de la route du modèle, il suffit donc de cliquer au bon endroit pour y accéder. Mais c'est un problème dans MQL. Ce qui peut devenir un casse-tête permanent pour le créateur du modèle.

Mais ça peut être réparé. Pour ce faire, vous pouvez utiliser la surcharge des modèles :

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

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

Maintenant, en essayant de passer la constante, le modèle supérieur sera appelé. Mais ce n'est pas une solution suffisante, car premièrement, l'erreur ne se produit que lors de la compilation de l'exécutable (et dans .mqh, ce n'est pas le cas), et deuxièmement, cette erreur se produit à l'endroit où le modèle est déclaré, et non à l'endroit où il est appelé, ce que nous voulons trouver. Donc, passons à autre chose.

Lorsque le modèle est une méthode d'une classe, tout est simple : nous plaçons le faux modèle dans une section privée et obtenons une erreur d'accès lorsque nous essayons de l'appeler.

Dans le cas d'une fonction simple, c'est plus compliqué. En C++, le problème ne peut pas être résolu par la surcharge seule, nous avons besoin d'une fonctionnalité supplémentaire, qui est absente dans MQL. Mais ici, l'arme puissante de MQL - les bogues - vient à notre aide ! ) Dans ce cas, l'un de ces bogues s'avère très utile pour nous ;)
Nous ajoutons un paramètre supplémentaire T2 à notre faux modèle et maintenant, lorsque nous essayons d'appeler le mauvais modèle, nous obtenons une erreur au point d'appel :

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
}

Problème résolu. En C++, le modèle inférieur sera bien sûr appelé dans les deux cas, car il n'y a pas de bogue de ce type.

Cette méthode peut être utile dans un autre cas : lorsque nous devons contrôler explicitement les types d'arguments de fonction, en désactivant la conversion implicite.
Par exemple, la fonction ne devrait accepter que l'argument datetime, en supprimant toutes sortes d'int et autres.
Nous faisons une variante correspondante :

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

void MyFunc(datetime time) {  }

Maintenant, comme dans le cas précédent, une erreur de compilation sera lancée en essayant de passer un type non résolu.

D'ailleurs, je fais toujours une telle interdiction pour datetime. Je pense que c'est pour rien que les développeurs ont autorisé une conversion implicite vers celle-ci du tout et sans aucun avertissement au compilateur (sauf pour long et string). Même n'importe quel enum est librement converti en lui sans aucun avertissement.

Il existe également le problème inverse : interdire uniquement un appel d'un certain type. La solution serait la même :

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

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


Comme mentionné ci-dessus, tout ce qui se trouve à l'intérieur de la classe est résolu sans paramètres inutiles.

 
Alexey Navoykov:

Dans la continuité de notre rubrique "mains vertigineuses", le sujet d'aujourd'hui est la fièvre du gabarit, ou comment se débarrasser d'un gabarit dans le cul).

Il est souvent nécessaire de passer une variable comme argument de modèle par référence pour la modifier.

Le besoin se fait sentir de passer par référence sans modification - pour la vitesse, ou un objet.

Toutefois, la spécification actuelle des modèles C++ ne permet malheureusement pas de spécifier explicitement la non-constance d'un argument, comme c'est le cas dans les fonctions habituelles :

Et cela peut causer des désagréments lorsque l'argument descend la chaîne de motifs jusqu'à sa destination et là, il s'avère être une constante et ne peut être modifié. Et cette erreur se produit quelque part dans les profondeurs des bibliothèques. Détecter d'où le modèle original a été appelé est parfois une tâche très difficile.

Existe-t-il un exemple réel dans MQL5 où ce problème se produit ?

Ce n'est pas un problème dans les IDE normaux. Dans VS, par exemple, la trace complète de la route du modèle est affichée, il suffit donc de cliquer au bon endroit pour y arriver. Mais dans MQL, c'est un vrai problème. Ce qui peut devenir un casse-tête permanent pour le créateur du modèle.

Mais ça peut être réparé. Pour ce faire, vous pouvez utiliser la surcharge des modèles :

Maintenant, en essayant de passer la constante, le modèle supérieur sera appelé. Mais ce n'est pas une solution suffisante, car premièrement, l'erreur ne se produit que lors de la compilation de l'exécutable (et dans .mqh, ce n'est pas le cas), et deuxièmement, cette erreur se produit à l'endroit où le modèle est déclaré, et non à l'endroit où il est appelé, ce que nous voulons trouver. Donc, passons à autre chose.

Lorsque le modèle est une méthode d'une classe, tout est simple : nous plaçons le faux modèle dans une section privée et obtenons une erreur d'accès lorsque nous essayons de l'appeler.

Dans le cas d'une fonction normale, cependant, c'est plus compliqué. Syntaxiquement, ce problème n'est pas du tout soluble en C++, pour autant que j'aie compris. Mais nous avons la chance que MQL ne soit pas C++ - il y a des bogues dedans ; et dans ce cas, ces bogues peuvent être contournés).

Nous ajoutons un paramètre supplémentaire T2 à notre faux modèle et nous obtenons une erreur au point d'appel lorsque nous essayons d'appeler le mauvais modèle :

Problème résolu. En C++, le modèle inférieur sera appelé dans les deux cas, bien sûr.

Le véritable exemple de commodité est absent.

Cette méthode peut être utile dans un autre cas : lorsque nous devons contrôler explicitement les types des arguments de la fonction, en désactivant la conversion implicite.
Par exemple, la fonction ne doit accepter que l'argument datetime, ce qui exclut toutes sortes d'int et d'autres éléments.
Nous faisons une variante correspondante :

Maintenant, comme dans le cas précédent, une erreur de compilation sera lancée en essayant de passer un type non résolu.

Il semble qu'il ait été utilisé dans MQL5 dans toute sa mesure, dès que la possibilité s'est présentée. Si je comprends bien, il s'agit d'une norme.

D'ailleurs, je fais toujours une telle interdiction pour datetime. Je pense que les développeurs n'auraient pas dû permettre la conversion implicite vers celle-ci, et même sans aucun avertissement au compilateur (sauf pour long et string). Même n'importe quel enum est librement converti en lui sans aucun avertissement.

Il existe également le problème inverse : interdire uniquement un appel d'un certain type. La solution serait similaire :

Expérimenter la commodité du comportement de l'heure de la date comme il le fait maintenant. Quand le problème se pose-t-il ?


Dans l'ensemble, il s'agit d'un article très bon et utile, merci !