OOP, templates et macros dans mql5, subtilités et utilisations - page 14

 
Artyom Trishkin:

1. Il est préférable de parler d'une chose à l'endroit où elle se trouve, plutôt que de penser à la façon dont le modérateur s'y prendrait. Sinon, tout s'est vraiment brouillé en deux fils et maintenant, même si le modérateur décide que la discussion doit être là ou là, c'est une tâche très lourde pour déplacer la discussion normalement en préservant l'ordre des messages et leur sens.

2) Discuter des actions d'un modérateur n'est pas à dédaigner... Ce n'est pas tous les éternuements, mais si vous voulez le défier publiquement, que ce soit pour rétablir l'ordre ou calmer une frénésie. Et si vous avez une opinion, qui vous interdit de l'exprimer ? Peut-être que votre opinion est une suggestion très rationnelle, mais que vous avez peur de la dire, pour ne pas tomber dans le menu mal aimé du modérateur ? Donc c'est des conneries :)

Merci pour cette précision. J'ai pensé qu'il valait mieux que la discussion ait lieu dans un fil distinct afin de ne pas encombrer les informations censées être précieuses dans le fil principal. Si vous décidez de déplacer les postes, je discuterai de l'endroit où vous les déplacez.

 
Ilya Malev:

Ce n'est pas comme si vous étiez déjà un modérateur, pour déterminer dans quel fil ce qui est plus approprié. Et les modérateurs ont déjà clairement indiqué que les discussions sur les fonctionnalités doivent se faire dans une branche séparée, c'est-à-dire ici, plutôt que dans la branche des fonctionnalités elle-même.

Dans votre description, il n'est pas du tout clair comment se référer uniformément à une méthode de classe par référence et par une valeur de type T. Je ne sais pas de quoi vous parlez, mais je parlais justement de cette chose là.

Voici la situation : j'ai réalisé que tout ne peut pas être adapté aux spécificités que les membres du forum s'attendent à voir dans ce fil de discussion. La discussion ici (et elle était là, donc je l'ai déplacée ici) porte sur un sujet assez spécifique, que j'ai décidé de séparer dans un fil distinct. Qu'il y ait des fonctionnalités plus générales et compréhensibles pour la majorité, et ici - des classes, des façons délicates de travailler avec elles, y compris les macros (quel casse-tête pour beaucoup).

 
Ilya Malev:

Merci pour cette précision. J'ai pensé qu'il valait mieux que la discussion ait lieu dans un fil distinct afin de ne pas encombrer les informations censées être précieuses dans le fil principal. Si vous décidez de déplacer les postes, je discuterai de l'endroit où vous les déplacez.

Gardons-le comme ça à partir de maintenant. Copiez simplement - si possible - l'exemple dont vous parlez dans votre propre message, qui fait référence à cet exemple (j'ai du mal à savoir où il a commencé). Ou, si vous ne pouvez plus modifier votre message, dites-moi en privé où coller quoi.

 
Artyom Trishkin:

Que ça reste comme ça à partir de maintenant. Copiez simplement - si possible - l'exemple discuté dans votre message, qui fait référence à cet exemple (il m'est difficile de savoir où il a commencé ici). Ou, si vous ne pouvez pas déjà éditer votre message, dites-moi en privé où coller quoi.

J'ai déjà copié le code ici depuis ce fil de discussion il y a quelques messages, donc aucune action supplémentaire n'est nécessaire, je pense.

 
Ilya Malev:

J'ai déjà copié le code de ce fil de discussion il y a quelques messages, donc aucune étape supplémentaire n'est nécessaire.

Bien.

 

Mise à jour sur le thème des interfaces via les modèles et la statique. Pour être plus précis, il ne s'agit pas d'interfaces, mais plutôt d'opérations paramétrables de manière pratique sur des types arbitraires, mises en œuvre par des classes externes. Dans ce cas, il s'agit de la comparaison (Comparer) et de la projection (Caster).

J'ai partiellement répondu à la critique précédente, la classe "interface" (bien que ce ne soit pas une interface) n'est pas héritée de la classe paramètre (une telle méthode n'a pas pris...), et sans utiliser dynamic_cast bien sûr. Espérons que ce modèle sera plus logique.

#property strict

#define  tnm typename
#define  ttt template<tnm T>
#define  ttf template<tnm F>
#define  ttr template<tnm R>
#define  tft template<tnm T,tnm F>
#define  up(P) (CheckPointer(P)!=POINTER_INVALID)

enum ECMP{ EQUAL=0, GREATER=1, LESSER=-1, UNDEF=INT_MAX };

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+

ttt class Type
 {
private:
  T item;
public:
  Type(){ ZeroMemory( item ); }
  Type *operator= (T par){ item = par; return &this; }
  T Get(){ return item; }
  
  ttf int operator!= ( Type<F>&par )
   { 
      int r = Comparer< Type< T > *, Type< F > * >::Get().Compare( &this, &par );
      
      if( r == UNDEF ) printf("Cannot compare %s to %s!",tnm(T),tnm(F));
      else{
        printf("%s (%s) to %s (%s) is %s",
          Caster<Type<T>*,string>::Get().Cast(&this), tnm(T),
          Caster<Type<F>*,string>::Get().Cast(&par),  tnm(F), Caster<ECMP,string>::Get().Cast((ECMP)r)); }
      return r; 
   }
 };

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+

tft class Comparer
 {
private:
  static Comparer *handle;
public:
  Comparer(){ if( handle == NULL ) handle = &this; }
  static Comparer *Get(){ return handle ; }
  virtual ECMP Compare( T, F ){ return UNDEF; }
 };

//---

tft Comparer *Comparer::handle=NULL;

tft class Caster
 {
private:
  static Caster *handle;
public:
  Caster(){ if( handle == NULL ) handle = &this; }
  static Caster *Get(){ return handle ; }
  virtual F Cast( T ){ F r; ZeroMemory(r); return r; }
 };

//---

tft Caster *Caster::handle=NULL;

ttt class ToStrCaster: public Caster<T,string>
 {
public:
  virtual string Cast( T ){ return "N/A"; }
 };

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+

class CmpIntToInt: public Comparer<Type<int>*,Type<int>*>
 {
public:
  virtual ECMP Compare( Type<int>* op1, Type<int>* op2 ){ return ECMP(up(op1)&&up(op2)?(op1.Get()>op2.Get())-(op1.Get()<op2.Get()):UNDEF); }
 }
citi;

class CmpDoubleToDouble: public Comparer<Type<double>*,Type<double>*>
 {
public:
  virtual ECMP Compare( Type<double>* op1, Type<double>* op2 ){ 
      return ECMP(up(op1)&&up(op2)?int(op1.Get()-op2.Get()>DBL_EPSILON)-int(op2.Get()-op1.Get()>DBL_EPSILON):UNDEF); }
 }
cdtd;

class CmpStrToStr: public Comparer<Type<string>*,Type<string>*>
 {
public:
  virtual ECMP Compare( Type<string>* op1, Type<string>* op2 ){ 
      return ECMP(up(op1)&&up(op2)?StringCompare(op1.Get(),op2.Get()):UNDEF); }
 }
csts;

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+

class IntToStrCaster: public ToStrCaster<Type<int>*>
 {
public:
  virtual string Cast( Type<int>* par ){ return up(par)?IntegerToString(par.Get()):NULL; }
 }
itsc;

class DoubleToStrCaster: public ToStrCaster<Type<double>*>
 {
public:
  virtual string Cast( Type<double>* par ){ return up(par)?DoubleToString(par.Get(),6):NULL; }
 }
dtsc;

class StringToStrCaster: public ToStrCaster<Type<string>*>
 {
public:
  virtual string Cast( Type<string>* par ){ return up(par)?par.Get():NULL; }
 }
stsc;

class ECMPToStrCaster: public ToStrCaster<ECMP>
 {
public:
  virtual string Cast( ECMP par ){ return EnumToString(par); }
 }
etsc;

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+

void OnStart()
 {
  Type<int> t1=AccountNumber(), t2=AccountLeverage();
  Type<double> t3=Ask, t4=Bid;
  Type<string> t5=_Symbol;
  
  t1!=t2;
  t4!=t3;
  t5!=t5;
  t1!=t3;
  t2!=t5;
 }


 

Est-il réaliste d'écrire une macro pour cette section de code ?

input int   InDealType_01=17;
input int   InDealType_02=22;
.....
input double InVolume_01 = 0.1;
input double InVolume_02 = 0.3;
.....    
   EA.AddDealsSettings(InDealType_01,InVolType_01,InVolume_01,InPrice_01,InVolCoeff_01,InClosePips_01,Mirror);
   EA.AddDealsSettings(InDealType_02,InVolType_02,InVolume_02,InPrice_02,InVolCoeff_02,InClosePips_02,Mirror);
   EA.AddDealsSettings(InDealType_03,InVolType_03,InVolume_03,InPrice_03,InVolCoeff_03,InClosePips_03,Mirror);
   EA.AddDealsSettings(InDealType_04,InVolType_04,InVolume_04,InPrice_04,InVolCoeff_04,InClosePips_04,Mirror);
   EA.AddDealsSettings(InDealType_05,InVolType_05,InVolume_05,InPrice_05,InVolCoeff_05,InClosePips_05,Mirror);
   EA.AddDealsSettings(InDealType_06,InVolType_06,InVolume_06,InPrice_06,InVolCoeff_06,InClosePips_06,Mirror);
   EA.AddDealsSettings(InDealType_07,InVolType_07,InVolume_07,InPrice_07,InVolCoeff_07,InClosePips_07,Mirror);
   EA.AddDealsSettings(InDealType_08,InVolType_08,InVolume_08,InPrice_08,InVolCoeff_08,InClosePips_08,Mirror);
   EA.AddDealsSettings(InDealType_09,InVolType_09,InVolume_09,InPrice_09,InVolCoeff_09,InClosePips_09,Mirror);
   EA.AddDealsSettings(InDealType_10,InVolType_10,InVolume_10,InPrice_10,InVolCoeff_10,InClosePips_10,Mirror);

Je n'ai pas encore décidé du nombre de variables d'entrée (entrée), je suis fatigué de corriger la section allouée, la macro pour une ligne n'est pas un problème, mais comment la multiplier à 10-15 lignes, je ne sais pas.

 
Igor Makanu:

Est-il réaliste d'écrire une macro pour cette section de code ?

je n'ai pas encore décidé du nombre de variables d'entrée (entrée), fatigué de corriger la partie sélectionnée, la macro pour une ligne n'est pas un problème, mais comment la multiplier à 10-15 lignes je ne sais pas

Je dois dire tout de suite que je ne l'ai pas vérifié sur µl, je l'ai juste fait passer par le préprocesseur cis pour le tester, µl a des particularités, donc si quelque chose ne va pas, veuillez le modifier.

#define  ARGS HLP(InDealType_)    \
             HLP(InVolType_),    \
             HLP(InVolume_),     \
             HLP(InPrice_),      \
             HLP(InVolCoeff_),   \
             HLP(InClosePips_),  \
             Mirror
#define _CAT(L, R) L##R
#define  CAT(L, R) _CAT(L, R)
#define  HLP(ARG)  CAT(ARG, INDEX)

#define  INDEX 01
EA.AddDealsSettings(ARGS);
#undef  INDEX
#define  INDEX 02
EA.AddDealsSettings(ARGS);
#undef  INDEX
#define  INDEX 03
EA.AddDealsSettings(ARGS);
#undef  INDEX

J'ai obtenu la sortie (gcc -E) :

EA.AddDealsSettings(InDealType_01 InVolType_01, InVolume_01, InPrice_01, InVolCoeff_01, InClosePips_01, Mirror);
EA.AddDealsSettings(InDealType_02 InVolType_02, InVolume_02, InPrice_02, InVolCoeff_02, InClosePips_02, Mirror);
EA.AddDealsSettings(InDealType_03 InVolType_03, InVolume_03, InPrice_03, InVolCoeff_03, InClosePips_03, Mirror);

arguments supplémentaires vous/donner à la liste ARGS.

 
Igor Makanu:

Est-il réaliste d'écrire une macro pour cette section de code ?

Je n'ai pas encore décidé du nombre de variables d'entrée (entrée), je suis fatigué de corriger la section allouée, la macro pour une ligne n'est pas un problème, mais comment la multiplier à 10-15 lignes , je ne sais pas.

#define  TEST(dId) EA.AddDealsSettings(InDealType_##dId,InVolType_##dId,InVolume_##dId,InPrice_##dId,InVolCoeff_##dId,InClosePips_##dId,Mirror)
#define  TEST2(d1,d2) do {TEST(d1);TEST(d2);} while(false)
#define  TEST3(d1,d2,d3) do{TEST2(d1,d2);TEST(d3);} while(false)
#define  TEST4(d1,d2,d3,d4) do{TEST2(d1,d2);TEST(d3,d4);} while(false)
....
#define  TEST100(d1,...d100) do{TEST50(d1,...d50);TEST50(d51,...d100);}while(false)

void OnStart()
  {
....
TEST4(01,02,03,04);
......
}

Jusqu'à présent, on n'a trouvé que ça. Si les développeurs avaient ajouté un nombre variable de paramètres, comme en C, il pourrait être plus court.

 
Vladimir Simakov:

Pour l'instant, c'est tout ce que j'ai trouvé. Si les développeurs vissaient un nombre variable de paramètres, comme en C, il serait possible de le rendre plus court.

Quelque chose que j'ai surcompliqué ;)).

Et laissez-les utiliser le premier, c'est probablement le meilleur.

#define  TEST(dId)
Ce n'est pas un problème d'écrire TEST plusieurs fois.