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

 
Dominik Egert #:
Yes, let's not even talk about mql "interfaces".

But, what is important about my example, it's not spaghetti code, because the calling of subfunctions is only for demo purposes (and can be used to remove const declarations and how to reduce the type even more.

What is relevant about the initially called functions are their signatures. In fact, you need to have all in all, referring to your example, 5 signatures for the function "push" and only two or one for the function pop.

So this is what I mean, if you can reduce it to a simple use case like that - write a demo class with those 5 signatures in a simple class that shows the applicability of that, it would be much more useful than that code and might motivate someone to look into it more deeply.

 
Amir Yacoby #:

So this is what I mean, if you can reduce it to a simple use case like that - 5 signatures in a simple class that shows the applicability of that, it would be much more useful than that code and might motivate someone to look into it more deeply.

May I encourage you to do that? My example just shows all possible paths, you can take. It's complete, not aimed at being simple....

I initially expected anyways only capable coders to be able to read and use it, as all others might just use STL anyways.

But, let me take a short look at it and maybe I can post a reference frame template.
 
Dominik Egert #:
May I encourage you to do that? My example just shows all possible paths, you can take. It's complete, not aimed at being simple....

I initially expected anyways only capable coders to be able to read and use it, as all others might just use STL anyways.

But, let me take a short look at it and maybe I can post a reference frame template.

I mean, you say that I need 5 push signatures, and not need the three classes (one base, two extensions that call only the protected base methods - they don't duplicate the logic) - so can you complete it or post a one class with 5 signatures. Becasue I still don't understand if that task is simple with your approach or not.

 
Amir Yacoby #:

I mean, you say that I need 5 push signatures, and not need the three classes (one base, two extensions that call only the protected base methods - they don't duplicate the logic) - so can you complete it or post a one class with 5 signatures. Becasue I still don't understand if that task is simple with your approach or not.

Yes, I can...

Here is a framework-structure, can be defined as class as well, depending on how you handle instances of your filo_buffer, or containers in general...

EDIT: Providing a fully working and tested example....


template <typename USER_DATA>
struct filo_buffer
{
    protected:
    const int   __pre_alloc;
    int         __ptr;
    USER_DATA   __internal_data[];
    

    public:
    // Constructors

        filo_buffer(const int pre_alloc  =25) :
            __pre_alloc (pre_alloc),
            __ptr       (NULL)
        {};


    // Push functions

        template <typename CALL_TYPE>
        const int push(CALL_TYPE& p_in[])
        { 
            const int element_count = ArraySize(p_in);
            for(int cnt = NULL; (cnt < element_count) && !_StopFlag; cnt++)
            { push(p_in[cnt]); }
            return(__ptr);
        };
    
        template <typename CALL_TYPE>
        const int push(CALL_TYPE* p_in)
        { 
            buffer_size();
            __internal_data[__ptr++] = p_in;
            return(__ptr);
        };
    
        template <typename CALL_TYPE>
        const int push(CALL_TYPE& p_in)
        { 
            buffer_size();
            __internal_data[__ptr++] = (USER_DATA)(p_in);
            return(__ptr);
        };
    
    
        template <typename CALL_TYPE>
        const int push(CALL_TYPE p_in) 
        { 
            buffer_size();
            __internal_data[__ptr++] = (USER_DATA)(p_in);
            return(__ptr);
        };
    
    
        const int push(USER_DATA& p_in)
        { 
            buffer_size();
            __internal_data[__ptr++] = p_in;
            return(__ptr);
        };

    
    // Pop and Piek

        USER_DATA pop()
        { __ptr--; return(__internal_data[__ptr]); }
    
    
        USER_DATA piek()
        { return(__internal_data[__ptr - 1]); }


    private:
    // Internal resize

        void buffer_size()
        { 
            const int arr_size = ArraySize(__internal_data);
            __ptr = (__ptr >= arr_size) ? (ArrayResize(__internal_data, arr_size + 1, 25) - 1) : __ptr;
            return;
        }
};



class MyObj
{   
    protected:
    
        int my_val;
    
    public:
    MyObj() :
        my_val  (NULL)
    { };

    MyObj(const MyObj& p_in) :
        my_val  (p_in.my_val)
    { };    
};



void OnStart()
{
    filo_buffer<datetime>   dtm_buffer();
    filo_buffer<MqlRates>   struct_buffer();
    filo_buffer<MyObj>      class_buffer();
    filo_buffer<MyObj*>     ptr_buffer();

    datetime    test_datetime[5];
    MqlRates    test_mqlrates[5];
    MyObj       test_myobj[5];
    MyObj*      test_myptr[5];
    
    
    dtm_buffer.push(D'01.01.1980 12:34:56');
    dtm_buffer.push(test_datetime);
    dtm_buffer.push(test_datetime[0]);
    test_datetime[0] = dtm_buffer.pop();

    struct_buffer.push(test_mqlrates);
    struct_buffer.push(test_mqlrates[0]);
    test_mqlrates[0] = struct_buffer.pop();

    class_buffer.push(test_myobj);
    class_buffer.push(test_myobj[0]);
    test_myobj[0] = class_buffer.pop();

    ptr_buffer.push(test_myptr);
    ptr_buffer.push(test_myptr[0]);
    test_myptr[0] = ptr_buffer.pop();
        
}

 
Dominik Egert #:

Yes, I can...

Here is a framework-structure, can be defined as class as well, depending on how you hadle instances of your fifo_buffer, or containers in general...

EDIT: Providing a fully working and tested example....


Yes, the template was enough to clarify the substance of the idea. That long discussion with Alain should be concluded with that because I think most people did not bother to follow those neuances and expected some kind of simplified conclusion like this one (yes, time is maybe most expensive these days). 

So now it's clear, nice work by Alain and yourself.

 
Amir Yacoby #:

Yes, the template was enough to clarify the substance of the idea. That long discussion with Alain should be concluded with that because I think most people did not bother to follow those neuances and expected some kind of simplified conclusion like this one (yes, time is maybe most expensive these days). 

So now it's clear, nice work by Alain and yourself.

Yes, your pushing is appreciated.

Now it values others as well... I guess we closed up the knowledge into a very complex development process.

The woods and the trees.... I guess we all fall for this once in a while.

Hope you can benefit from that, and I don't have to provide more support to it.
 
Dominik Egert #:
Yes, your pushing is appreciated.

Now it values others as well... I guess we closed up the knowledge into a very complex development process.

The woods and the trees.... I guess we all fall for this once in a while.

Hope you can benefit from that, and I don't have to provide more support to it.

No, that could not be left as it was. You two followed the process in your discussions, and very good you motivated each other, because your findings are too big to be left aside. Yes, you bothered to lay down all the trees in the playground, but I think most people did not even try to see the forest and follow your path themselves becuase they wrongly assumed that you post some kind of forest. At least I did. 

But again, you two made great revelation, really.

 
Dominik Egert #:

Yes, I can...

Here is a framework-structure, can be defined as class as well, depending on how you handle instances of your filo_buffer, or containers in general...

EDIT: Providing a fully working and tested example....


BTW, I don't quite understand the use of that signature, I removed it and it still works

        template <typename CALL_TYPE>
        const int push(CALL_TYPE& p_in)
        { 
            buffer_size();
            __internal_data[__ptr++] = (USER_DATA)(p_in);
            return(__ptr);
        };
 
Amir Yacoby #:

BTW, I don't quite understand the use of that signature, I removed it and it still works

Pass in an object of derived type, thats what it is for.

EDIT:

Usage is for a container of type pointer, where you want to pass in an object by reference and get a pointer from it and assign it to the base class pointer type.

Or, when looking at my Playground example, lets say you are using a derived type of MqlRates and you want to be able to pass in a struct of base-type MqlRates from a MQL Systemcall iE CopyRates(), and want to be able to assign the struct to its derived type.

There is a reason why the playground needs to be understood, and it all depends on your specific usecase, of course.

 

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.