OOP, plantillas y macros en mql5, sutilezas y usos - página 14

 
Artyom Trishkin:

1. Es mejor hablar de algo en el lugar donde se encuentra, en lugar de pensar en cómo lo haría el moderador. De lo contrario, todo se desdibujó en dos hilos, y ahora, aunque el moderador decida que la discusión debe estar ahí o allá, es una tarea bastante laboriosa mover la discusión normalmente con la preservación del orden de los mensajes y su significado.

2) Discutir las acciones de un moderador no es cualquier estornudo... No es cualquier estornudo, pero si quiere desafiarlo públicamente, ya sea para restablecer el orden o para calmar el frenesí. Y si tienes una opinión, ¿quién te prohíbe expresarla? ¿Quizás tu opinión es una sugerencia muy racional, pero tienes miedo de decirla, para no caer en el menú no querido del moderador? Así que eso es una mierda :)

Gracias por la aclaración. Pensé que era mejor tener la discusión en un hilo separado para no desordenar la información supuestamente valiosa en el hilo principal. Si decides mover los puestos, discutiré dónde los mueves.

 
Ilya Malev:

No es que seas un moderador todavía, para determinar en qué hilo lo que es más apropiado. Y los moderadores ya han dejado claro que la discusión de las características no debe estar en la rama de características, sino en una rama aparte, es decir, aquí.

En su descripción, no queda nada claro cómo referirse uniformemente a un método de la clase por referencia y por un valor de tipo T. No sé de qué estás hablando, pero yo estaba hablando de esto mismo allí.

La situación es la siguiente: me he dado cuenta de que no todo puede adaptarse a los detalles que los miembros del foro esperan ver en ese hilo. La discusión aquí (y estaba allí, así que la he movido aquí) es un tema bastante específico, que he decidido separar en un hilo aparte. Que haya más general y comprensible a la mayoría de las características, y aquí - las clases, las formas difíciles de trabajar con ellos, incluyendo macros (lo que es un rompecabezas para muchos).

 
Ilya Malev:

Gracias por la aclaración. Pensé que era mejor tener la discusión en un hilo separado para no desordenar la información supuestamente valiosa en el hilo principal. Si decides mover los puestos, discutiré dónde los mueves.

Que siga siendo así a partir de ahora. Simplemente -si es posible- copia el ejemplo que comentas de ahí en tu propio post, que hace referencia a ese ejemplo (me cuesta saber dónde empezó). O, si ya no puedes editar tu post, entonces dime en privado de dónde pegar qué.

 
Artyom Trishkin:

Que siga siendo así a partir de ahora. Sólo -si es posible- copia el ejemplo discutido de allí en tu post, que hace referencia a ese ejemplo (me cuesta entender qué empezó aquí). O, si no puedes ya editar tu post, entonces dime en privado de dónde pegar qué.

Ya copié el código aquí desde ese hilo hace un par de posts, así que no es necesaria ninguna acción adicional, imho.

 
Ilya Malev:

Ya copié el código de ese hilo hace un par de posts, así que no hace falta ningún paso extra.

Bien.

 

Actualización sobre el tema de las interfaces a través de las plantillas y la estática. Para ser más precisos, no son interfaces, sino operaciones convenientemente parametrizables sobre tipos arbitrarios, implementadas a través de clases externas. En este caso, la comparación (Comparer) y la fundición (Caster).

He atendido parcialmente la crítica anterior, la clase "interfaz" (aunque no es una interfaz) no se hereda de la clase parámetro (tal método no se ha puesto de moda...), y sin usar dynamic_cast por supuesto. Esperemos que este modelo sea más lógico.

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


 

¿Qué tan realista es escribir una macro para esta sección de código?

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

Todavía no he decidido el número de variables de entrada ( input ), estoy cansado de corregir la sección asignada, la macro para una línea no es un problema, pero cómo multiplicarla a 10-15 líneasno lo sé

 
Igor Makanu:

¿Qué tan realista es hacer una macro para esta sección de código?

aún no han decidido sobre el número de variables de entrada ( entrada ), cansado de corregir la parte seleccionada, la macro para una línea no es un problema, pero la forma de multiplicar a 10-15 líneas que no

Debo decir de una vez que no lo comprobé en µl, sólo lo pasé por un preprocesador sish para probarlo, µl tiene peculiaridades, si hay que afinar algo.

#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

Tengo la salida (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);

argumentos adicionales que usted / donar a la lista de ARGS.

 
Igor Makanu:

¿Qué tan realista es escribir una macro para esta sección de código?

Todavía no he decidido el número de variables de entrada ( input ), estoy cansado de corregir la sección asignada, la macro para una línea no es un problema, pero cómo multiplicarla a 10-15 líneas no lo sé

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

Hasta ahora, sólo se ha llegado a eso. Si los desarrolladores hubieran añadido un número variable de parámetros, como en C, podría ser más corto.

 
Vladimir Simakov:

Hasta ahora, esto es todo lo que se me ha ocurrido. Si los desarrolladores metieran un número variable de parámetros, como en C, sería posible hacerlo más corto.

Algo que he complicado en exceso )).

Y que usen el primero, probablemente sea el mejor.

#define  TEST(dId)
No es un problema escribir TEST varias veces.