OOP, templates and macros in mql5, subtleties and uses - page 14

 
Artyom Trishkin:

1. It is better to talk about something in the place where it is, rather than thinking about how the moderator would do it. Otherwise, everything really got blurred into two threads, and now, even if the moderator decides that the discussion should be there or there, it is quite a laborious task to move the discussion normally with preserving the order of the posts and their meaning.

2) Discussing the actions of a moderator isn't every sneeze... It's not every sneeze, but if you want to challenge him publicly, be it for restoring order or calming a frenzy. And if you have an opinion, who forbids you to express it? Maybe your opinion is a very rational suggestion, but you are afraid to say it, so as not to fall under the moderator's unloved menu? So that's bullshit :)

Thanks for the clarification. I thought it best to have the discussion in a separate thread so as not to clutter up the supposedly valuable information in the main thread. If you decide to move the posts, I will discuss where you move them.

 
Ilya Malev:

It's not like you're a moderator yet, to determine in which thread what is more appropriate. And moderators have already made it clear that discussion of features should not be in the feature branch, but in a separate branch, i.e. here.

In your description, it is not clear at all how to refer uniformly to a class method by reference and by a T-type value. I don't know what you are talking about, but I was talking about this very thing there.

Here's the situation: I realized that not everything can be tailored to the specifics that forum members expect to see in that thread. The discussion here is (and it was there, so I moved it here) about a fairly specific topic, which I decided to separate out into a separate thread. Let there be more general and understandable to the majority of features, and here - classes, tricky ways of work with them, including macros (what a puzzle for many).

 
Ilya Malev:

Thanks for the clarification. I thought it best to have the discussion in a separate thread so as not to clutter up the supposedly valuable information in the main thread. If you decide to move the posts, I will discuss where you move them.

Let's keep it that way from now on. Just - if possible - copy the example you're discussing from there into your own post, which refers to that example (I'm having trouble figuring out where it started). Or, if you can no longer edit your post, then tell me in private where to paste what from.

 
Artyom Trishkin:

Let it stay that way from now on. Just - if possible - copy the discussed example from there into your post, which refers to that example (it's hard for me to figure out what started it here). Or, if you can't already edit your post, then tell me in private where to paste what from.

I already copied the code here from that thread a couple of posts ago, so no additional action is needed, imho.

 
Ilya Malev:

I already copied the code from that thread a couple of posts ago, so no extra steps are required.

Good.

 

Update on the topic of interfaces via templates and statics. To be more precise, not interfaces, but rather conveniently parametrizable operations on arbitrary types, implemented through external classes. In this case, the comparison (Comparer) and casting (Caster).

I have partially addressed the previous criticism, the "interface" class (though it's not an interface) is not inherited from the parameter class (such a method hasn't caught on...), and without using dynamic_cast of course. Hopefully this model will look more logical.

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


 

How realistic is it to write a macro for this code section?

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

I have not decided yet on the number of input variables ( input ), I'm tired to correct the allocated section, the macro for one line is not a problem, but how to multiply it to 10-15 linesI do not know

 
Igor Makanu:

How realistic is it to write a macro for this code section?

have not decided yet on the number of input variables ( input ), tired to correct the selected part, the macro for one line is not a problem, but how to multiply it to 10-15 lines I do not know

I must say straightaway I did not check it on µl, I just ran it through cis preprocessor for testing, µl has peculiarities, so if something goes wrong, please modify it.

#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

got the output (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);

additional arguments you/donate to ARGS list.

 
Igor Makanu:

How realistic is it to write a macro for this code section?

I have not decided yet on the number of input variables ( input ), I'm tired to correct the allocated section, the macro for one line is not a problem, but how to multiply it to 10-15 lines I do not know

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

So far, only so come up with. If the developers had added a variable number of parameters, like in C, it could be shorter.

 
Vladimir Simakov:

So far, this is all I've come up with. If developers would screw in variable number of parameters, like in C, it would be possible to make it shorter.

Something I overcomplicated )).

And let them use the first one, it's probably best.

#define  TEST(dId)
It's not a problem to write TEST several times.