Writing generic code in MQL for Objects [solved] - page 7

 
Alain Verleyen #:

I don't consider I played a serious role on this, it's Dominik's merit, he has demonstrated it's "possible".

I am personally not satisfied with such solution, having to write 4 versions (at least) of a method each time you need something "generic". This is not even considering the const correctness. I am still hoping and trying to have some improvements on MQL itself. We will see.

Everyone is free to use it or not, so that's a step forward.

There might be slight improvements to this 4 versions of a method each time, like:

        template <typename CALL_TYPE>
        const int push(CALL_TYPE p_in) 
        { 
            CALL_TYPE pass=p_in;
            return push(pass);			// call reference type for primitive literal
        };

Which btw demonstates in my opinion that MQL might improve in that at least do it automatically (passing int primitive as reference that is like c++ does) instead of letting us do it manually like that

And also it's possible for the pointer version to the reference type - which leaves us with 2 versions of the same method only

        template <typename CALL_TYPE>
        const int push(CALL_TYPE* p_in)
        { 
            return push(p_in);
        };
Which also means in my mind, that if we have only the reference signature, MQL can make it by it's own and save us from needing to specify this pointer signature
 
Amir Yacoby #:

There might be slight improvements to this 4 versions of a method each time, like:

Which btw demonstates in my opinion that MQL might improve in that at least do it automatically (passing int primitive as reference that is like c++ does) instead of letting us do it manually like that

And also it's possible for the pointer version to the reference type - which leaves us with 2 versions of the same method only

Which also means in my mind, that if we have only the reference signature, MQL can make it by it's own and save us from needing to specify this pointer signature
It strongly depends on your use case.

Your first signature is also valid, of course.C/C++ allows us to make implizit copies, in MQL we have to do them on our own. But, yes, of course you can use the signature to just call the appropriate other function.

EDIT: (you can actually call the other function directly with the parameter p_in, you don't need to copy it, that has been done already by the callstack, saving you the copy operation)

Leaving out the pointer signature will lead to problems in the code, when you need distinguishing between pointer and value type.

As said, it all depends on your usecase.
 
Alain Verleyen #:

I don't consider I played a serious role on this, it's Dominik's merit, he has demonstrated it's "possible".

I am personally not satisfied with such solution, having to write 4 versions (at least) of a method each time you need something "generic". This is not even considering the const correctness. I am still hoping and trying to have some improvements on MQL itself. We will see.

Everyone is free to use it or not, so that's a step forward.

Yes, but you were the counterplay to it, and you gave the insight I needed to finally find a solution. So, I think it's also your praise.

Yes, "possible"... true. And I do agree it is sort of ugly.But in the end, if it's encapsulated inside a library, the usage is quite seem less and leads to less cluttered code.

I am not quite sure what you refer to with const correctness, as the templates do expand const correctly (most of the time). That was one of the points we struggled with. But maybe you are referring to the strange behaviour of const being dropped occasionally and as I personally think wrongly by the compiler when it comes to primitive types.

BTW, do you need an example still for this type of behaviour? Or did you pass that already forward to MQ?
 

Just to be sure, the calling of ref signature from ptr signature does not create a copy of the object, it just passes its reference.

 
Amir Yacoby #:

Just to be sure, the calling of ref signature from ptr signature does not create a copy of the object, it just passes its reference.

I understood you removed the ptr signature?!

And I was referring to this:

        template <typename CALL_TYPE>
        const int push(CALL_TYPE p_in) 
        { 
            CALL_TYPE pass=p_in;
            return push(pass);			// call reference type for primitive literal
        };

Which can be written like this:

        template <typename CALL_TYPE>
        const int push(CALL_TYPE p_in) 
        {
            return push(p_in);			// call reference type for primitive literal
        };

EDIT:
This can lead to recursion and calling itself until you hit a stack overflow... Depends on what you are doing.

I would like to close this, as I am sure everything required is provided and can be discovered individually. Please be adviced, it's been a lot of work to narrow everything down, and it is not simple, or easy.

Working versions have been provided, and they have their validity as they stand. Adapting this to your personal needs may be beneficial to your code, but might lead to non-universality of the code.

A simple FiLo buffer example was provided, as well as the whole development process with all possible situations.

It is up to the individual reader to figure out what parts are required to cover theyr needs.

I am not saying this to offend anyone, but it needs to be understood, I do not intend to elaborate each variation with each individual on the relevant and relevances of specific implementations.

I am though, willing to accept errors, bugs and improvements, if they proof to work in all cases.

The bottom line goal is to have one function name that is capable of being called with any available data type.
 
Dominik Egert #:
I understood you removed the ptr signature?!

And I was referring to this:


Which can be written like this:

Ok, I know that. For some reason I changed it because I have a different implementation of the fifo_buffer from yours, and I copied from mine to your's and it got somehow confused.

But I tested the passing of an object to a ref, just to be sure it does not create a copy of the object (which it does not)

class A
  {
private:
   int               m_id;
public:
                     A() {A_ID++; m_id=A_ID;}
   static int        A_ID;
   int               ID() const {return m_id;}
  };
int A::A_ID=0;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class B
  {
private:
   A                 *m_objp;
   A                 *m_objr;
private:
   //--- object recieved from ptr - compare to m_objp
   bool              Ref(A &objr)
     {
      m_objr=GetPointer(objr);
      Print("Object passed from ptr signature: obj id=",m_objp.ID()," ref id=",m_objr.ID(), " Equals=",m_objp==m_objr);
      return m_objp==m_objr;
     }
public:
   //--- compare ptr and compatible ref and return result
   bool              Obj(A *objp)
     {
      m_objp=objp;
      return Ref(objp);
     }
  };
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   A  *ap1=new A();
   A  *ap2=new A();
   Print("ap1.ID()=",ap1.ID()," ap2.ID()=",ap2.ID());
   B  check();
   Print("ap1 passed as pointer equals the reference ? ",check.Obj(ap1));
  }

But using that shifting from ptr to ref still has a drawback for derived classes, which it does not resolve into the reference type

 
Amir Yacoby #:

Ok, I know that. For some reason I changed it because I have a different implementation of the fifo_buffer from yours, and I copied from mine to your's and it got somehow confused.

But I tested the passing of an object to a ref, just to be sure it does not create a copy of the object (which it does not)

But using that shifting from ptr to ref still has a drawback for derived classes, which it does not resolve into the reference type

Yes, it is not trivial.

Please don't be offended, but I do not intend to step through each development process piece by piece with you again.

Please consider understanding Playground and find how to test your variations. I have spent hours and days to melt it all down to these 4 signatures....
 
Dominik Egert #:
Yes, it is not trivial.

Please don't be offended, but I do not intend to step through each development process piece by piece with you again.

Please consider understanding Playground and find how to test your variations. I have spent hours and days to melt it all down to these 4 signatures....

It's totally accepted, you did a great job again. The shifting from class level templating to method templating level on top of class templating to achieve isolation of the calls was a brilliant idea.

 
Amir Yacoby #:

It's totally accepted, you did a great job again. The shifting from class level to method templating level on top of class templating to achieve isolation of the calls was a brilliant idea.

Thank you for the flowers.... Appreciated.