is it possible to create a varargs function?

 

I would like to create a function which can accept a variable # of parameters.

I want to do this to then pass these parameters to PrintFormat() or StringFormat();

Is this possible?

e.g. 

myfunc("abc %d", 10);


or  

myfunc("abc %d:%d %s", 10,20,"awqe"); 


if this is not directly possible, then is it possible through templates? I know you can do it with templates in C++ and I heard that MetaTrader supports templates.

 
ycomp:I would like to create a function which can accept a variable # of parameters. I want to do this to then pass these parameters to PrintFormat() or StringFormat(); Is this possible? if this is not directly possible, then is it possible through templates? I know you can do it with templates in C++ and I heard that MetaTrader supports templates.

No, MQL does not support user defined variadic functions. Normally I would say, ... search the forum for the keyword "variadic" for more information and other options, ...

... but currently the site's search is malfunctioning so here is the "Google" option ... https://www.google.com/search?q=site%3Amql5.com+variadic

 
ycomp:

I would like to create a function which can accept a variable # of parameters.

I want to do this to then pass these parameters to PrintFormat() or StringFormat();

Is this possible?

e.g. 


or  


if this is not directly possible, then is it possible through templates? I know you can do it with templates in C++ and I heard that MetaTrader supports templates.

This should have worked (up to 16 parms, can easily be extended), but it seems that there is a bug compiling this code, compiler assumes parms to PrintFormat are all strings.

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   MqlParam p[16];
   p[0].type=TYPE_STRING;
   p[0].string_value="The fx trader";
   p[1].type=TYPE_INT;
   p[1].integer_value=5;
   p[2].type=TYPE_INT;
   p[2].integer_value=16;
   p[3].type=TYPE_DOUBLE;
   p[3].double_value=16.0;
   p[4].type=TYPE_STRING;
   p[4].string_value="just an example";
   MyFunc("this is %s showing a call with %d out of %d and just to put the double value %.2f %s",p);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void MyFunc(const string str,MqlParam &parms[])
  {
   PrintFormat(str,
               (parms[0].type==TYPE_STRING) ? parms[0].string_value : parms[0].type==TYPE_DOUBLE ? parms[0].double_value : parms[0].integer_value,
               (parms[1].type==TYPE_STRING) ? parms[1].string_value : parms[1].type==TYPE_DOUBLE ? parms[1].double_value : parms[1].integer_value,
               (parms[2].type==TYPE_STRING) ? parms[2].string_value : parms[2].type==TYPE_DOUBLE ? parms[2].double_value : parms[2].integer_value,
               (parms[3].type==TYPE_STRING) ? parms[3].string_value : parms[3].type==TYPE_DOUBLE ? parms[3].double_value : parms[3].integer_value,
               (parms[4].type==TYPE_STRING) ? parms[4].string_value : parms[4].type==TYPE_DOUBLE ? parms[4].double_value : parms[4].integer_value,
               (parms[5].type==TYPE_STRING) ? parms[5].string_value : parms[5].type==TYPE_DOUBLE ? parms[5].double_value : parms[5].integer_value,
               (parms[6].type==TYPE_STRING) ? parms[6].string_value : parms[6].type==TYPE_DOUBLE ? parms[6].double_value : parms[6].integer_value,
               (parms[7].type==TYPE_STRING) ? parms[7].string_value : parms[7].type==TYPE_DOUBLE ? parms[7].double_value : parms[7].integer_value,
               (parms[8].type==TYPE_STRING) ? parms[8].string_value : parms[8].type==TYPE_DOUBLE ? parms[8].double_value : parms[8].integer_value,
               (parms[9].type==TYPE_STRING) ? parms[9].string_value : parms[9].type==TYPE_DOUBLE ? parms[9].double_value : parms[9].integer_value,
               (parms[10].type==TYPE_STRING) ? parms[10].string_value : parms[10].type==TYPE_DOUBLE ? parms[10].double_value : parms[10].integer_value,
               (parms[11].type==TYPE_STRING) ? parms[11].string_value : parms[11].type==TYPE_DOUBLE ? parms[11].double_value : parms[11].integer_value,
               (parms[12].type==TYPE_STRING) ? parms[12].string_value : parms[12].type==TYPE_DOUBLE ? parms[12].double_value : parms[12].integer_value,
               (parms[13].type==TYPE_STRING) ? parms[13].string_value : parms[13].type==TYPE_DOUBLE ? parms[13].double_value : parms[13].integer_value,
               (parms[14].type==TYPE_STRING) ? parms[14].string_value : parms[14].type==TYPE_DOUBLE ? parms[14].double_value : parms[14].integer_value,
               (parms[15].type==TYPE_STRING) ? parms[15].string_value : parms[15].type==TYPE_DOUBLE ? parms[15].double_value : parms[15].integer_value
              );
  }
 
Amir Yacoby #: but it seems that there is a bug compiling this code, compiler assumes parms to PrintFormat are all strings.

No compiler bug there, PICNIC. The type of the Ternary Operator ?: is the type of the first value. You are passing only strings.

 
William Roeder #:

No compiler bug there, PICNIC. The type of the Ternary Operator ?: is the type of the first value. You are passing only strings.

I stand corrected.

I did a trial before posting, it was not the first value, I did recall I made it with second value.
Its because it's not the first value, it's the max value - which still doesn't change the fact that it's really not a compiler bug.

 
As I need it as well, I hope to come up with some kind of solution till tomorrow - will publish here. 
 
Amir Yacoby #:
As I need it as well, I hope to come up with some kind of solution till tomorrow - will publish here. 

Using this https://www.mql5.com/en/code/16282 library it should be possible.


I use it to pass data to OnTesterPass From Ontester.

// from Ontester:
 
         CONTAINER<uchar> Container;
          Container[0] = Result;
          Container[1] = Intervals;
          Container[2] = Data;
          Container[3] = JSON;  
          FrameAdd("Statistics",inNTD,0,Container.Data);


// from OnTesterPass:
    CONTAINER <uchar> Container;
     double Result[];
     INTERVAL Intervals[];
     string Data[];
     string JSON[];
    while(FrameNext(Pass,Name,ID,Value,Container.Data))
    {

      Container[0].Get(Result);
      Container[1].Get(Intervals);
      Container[2].Get(Data);
      Container[3].Get(JSON);
...
 
Enrique Dangeroux #:

Using this https://www.mql5.com/en/code/16282 library it should be possible.


I use it to pass data to OnTesterPass From Ontester.

what do the single slashes do on the definitions \ ?

 

#define EQUAL_DEFINE(A)                 \
  template <typename T1>                \
  bool operator ==( const T1 &A ) const \
  {                                     \
    return(::ArrayCompare(this.Bytes,   \
           _R(Value).Bytes) == 0);      \
  }                                     \
                                        \
  template <typename T1>                \
  bool operator !=( const T1 &A ) const \
  {                                     \
    return(!(this == Value));           \
  }
 
Lorentzos Roussos #:

what do the single slashes do on the definitions \ ?

 

Multi line defines. Otherwise it should be a single line #define

 
Andrey Barinov #:

Multi line defines. Otherwise it should be a single line #define

Nice , thank you

Reason: