Assignment operator / default return value - possible?

Doerk Hilger
1756
Doerk Hilger  

Is there any way to define with operator overloading, that a class returns a kind of a default value?


class CInt
   {
   public: int value;
   
   public: void operator                       =  (CInt &other)          { value=other.value; }
   public: void operator                       =  (int other)            { value=other; }
   };

int OnInit()
   {
   //--- Fine
   CInt test=25;
   
   //--- Is this possible somehow?
   int i=test;
   
   //----
   return(INIT_FAILED);
   }
Fernando Carreiro
5705
Fernando Carreiro  
Doerk Hilger: Is there any way to define with operator overloading, that a class returns a kind of a default value?

I've never tried something like that before and it probably is not possible, since that would override its default type of it being a "object".

However, I have overridden the [] operator before to make it act like an array, and you probably can also override the () operator to make it act like a function call as something like "int i=test();"

EDIT: It does not seem like MQL supports overriding the () operator, so it will probably not work. However, overriding the [] operator does work and I have used it often!

Dominik Egert
1527
Dominik Egert  
Going along with the ordered execution of the statement

int i = xyz;

You need to understand the assignment operator is to be seen as a function of the "object" i as a type int.

So what you would need to do is a redefined Copy-Constructor, returning the target type, here int.

Another and probably better way of going along would be a function template, taking in the "i" as reference and assigning it this way.

At least for mql I cannot think of another consistent way of doing it.


Fernando Carreiro
5705
Fernando Carreiro  
Dominik Egert: Going along with the ordered execution of the statement

int i = xyz;

You need to understand the assignment operator is to be seen as a function of the "object" i as a type int. So what you would need to do is a redefined Copy-Constructor, returning the target type, here int. Another and probably better way of going along would be a function template, taking in the "i" as reference and assigning it this way. At least for mql I cannot think of another consistent way of doing it.

Although I am not the OP; I am also interested in a solution! However, my experience and knowledge level of OOP is only that of an intermediate level, so if you could give an example of the two possibilities, it would be greatly appreciated.

Dominik Egert
1527
Dominik Egert  
Fernando Carreiro:

Although I am not the OP; I am also interested in a solution! However, my experience and knowledge level of OOP is only that of an intermediate level, so if you could give an example of the two possibilities, it would be greatly appreciated.

Hi, let me try.

The issue is the target type, here "int" as it is given as fundamental type declaration by the compiler, there is no way to "extend" the underlying assignment-operator. Therefore it will be necessary to "modify" the source type and use it as a "source" for the target.


Since following is not possible:

class int
{
        int value;
        int& operator = (int arg) { value = i; }
};


A way to solve the issue would be to use a copy-constructor:

class A
{
    int n;
    A(int n = 1) : n(n) { }
    A(const A& a) : n(a.n) { } // user-defined copy ctor
};

 Where type int would be modified to a template, making the class versatile to the type given.

template <typename T>
class A
{
    T n;
    A(T n = (T)1) : n(n) { }
    A(const A& a) : n(a.n) { } // user-defined copy ctor
};


These are theoretical solutions, ive not tested them to be valid. But it sould explain the underlying mechanics to be used.

So the assignment given by OP would need to be changed to:

{
        int i
        A ci = i;
}


This will turn the assignment around, putting you into the position to influence the behaviour of the assignment and copy constructor. The above shown example does call the "operator = (...)" function, which now needs overloading.


Here is the C/C++ docs, explaining the concepts in more details:

https://en.cppreference.com/w/cpp/language/copy_constructor

and

https://en.cppreference.com/w/cpp/language/converting_constructor

and

https://en.cppreference.com/w/cpp/language/copy_assignment


Please note, in C/C++ struct and class are (almost) the same.

SInce MQL is missing some crucial implementations in concern of the constructors, I cannot really define a different way of handling the type, either in return or in assignment/parameter values given.

I suppose, some experimenting will be needed to understand the exact flow of the compilers handling. (But I suppose it wont be possible without some brain acrobatics and limitations in the usage of such an object)


So my suggestion to have full control of the types is to replace all fundamental types with self maintained template-objects to have all the power unleashed and assignment being unidirectional.

A template class to be used and then specific-instanciated on every use. This way you get objects, containing your specific and generalized assignment and copy operators. - This now has the issue, you cannot return objects from functions as return type in mql. The language is limited in such a way that ie lambdas are not possible and such operator overloading is only limited.

Fernando Carreiro
5705
Fernando Carreiro  
Dominik Egert: The issue is the target type, here "int" as it is given as fundamental type declaration by the compiler, there is no way to "extend" the underlying assignment-operator. Therefore it will be necessary to "modify" the source type and use it as a "source" for the target.

Since following is not possible:

A way to solve the issue would be to use a copy-constructor:

 Where type int would be modified to a template, making the class versatile to the type given.

These are theoretical solutions, ive not tested them to be valid. But it sould explain the underlying mechanics to be used.

So the assignment given by OP would need to be changed to:

This will turn the assignment around, putting you into the position to influence the behaviour of the assignment and copy constructor. The above shown example does call the "operator = (...)" function, which now needs overloading.

...

SInce MQL is missing some crucial implementations in concern of the constructors, I cannot really define a different way of handling the type, either in return or in assignment/parameter values given.

I suppose, some experimenting will be needed to understand the exact flow of the compilers handling. (But I suppose it wont be possible without some brain acrobatics and limitations in the usage of such an object)

So my suggestion to have full control of the types is to replace all fundamental types with self maintained template-objects to have all the power unleashed and assignment being unidirectional.

A template class to be used and then specific-instanciated on every use. This way you get objects, containing your specific and generalized assignment and copy operators. - This now has the issue, you cannot return objects from functions as return type in mql. The language is limited in such a way that ie lambdas are not possible and such operator overloading is only limited.

Ok, I think I understand it better, but, the resulting implementation would make the readability of code completely reversed, given that the code "A ci = i;" would be read as value of "i" being assigned to "ci", when from what I understand in your explanation, it is actually doing the opposite and assigning the internal int value of "ci"' to the variable "i".

It achieves the goal but would only confuse future readability of the code. I personally would just continue using the more standard method of "i = ci.value()", which is much more readable to me.

Any way, thank you for your explanation as I have learned something new today!

Dominik Egert
1527
Dominik Egert  
Fernando Carreiro:

Ok, I think I understand it better, but, the resulting implementation would make the readability of code completely reversed, given that the code "A ci = i;" would be read as value of "i" being assigned to "ci", when from what I understand in your explanation, it is actually doing the opposite and assigning the internal int value of "ci"' to the variable "i".

It achieves the goal but would only confuse future readability of the code. I personally would just continue using the more standard method of "i = ci.value()", which is much more readable to me.

Any way, thank you for your explanation as I have learned something new today!

Jap, right. - Thats an issue.

Although, if you remove all fundamental types and replace them with an templated class-object, this could be avoided. This way you get an object where you can overload the assignment-operator and encapusalte this "reverse assignment" into the functions body, it would mean you need to abandon all fundamental types.

Example:

template <typename T>
class fundamental_type
{
        // Fundamental value
        protected:
        T value;

        // Constructors
        void                    fundamental_type()              {};
        fundamental_type&       fundamental_type(T& arg)        { value = arg.value; }


        fundamental_type&       operator = (const T& arg)       { value = arg.value; }

        // [...]
        // Need to implement all available operators, since they are not given implicit.
};


// Main
void main()
{

        fundamental_type<int>   i = 0;

        fundamental_type<int>   c_obj = i;
}

(theoretical code)


As you can see, there would be a full redifinition of all fundamental types needed, since mql has only support for those types, all functions like ArrayFill() and so on would render useless... and need own implementation.

But they all could be (except for some exceptions) implemented inside this one fundamental object and new, other behaviour could be easily derived from the baseclass. (I have left out all types of deriving definitions in this example, like virtual and final.)

Additionally, when using arrays, this could be advanced beyont the current abilities of mql, especially memory management, smart pointers and so on. - Lots of work and lots of possibilities. But not very MQL-Like code anymore.


Jsut as a concept, to extend way beyond the capabilities of the (very limited) mql-compiler.

Welcome.
Fernando Carreiro
5705
Fernando Carreiro  

Dominik Egert: Jap, right. - Thats an issue. Although, if you remove all fundamental types and replace them with an templated class-object, this could be avoided. This way you get an object where you can overload the assignment-operator and encapusalte this "reverse assignment" into the functions body, it would mean you need to abandon all fundamental types.

As you can see, there would be a full redifinition of all fundamental types needed, since mql has only support for those types, all functions like ArrayFill() and so on would render useless... and need own implementation.

But they all could be (except for some exceptions) implemented inside this one fundamental object and new, other behaviour could be easily derived from the baseclass. (I have left out all types of deriving definitions in this example, like virtual and final.)

Additionally, when using arrays, this could be advanced beyont the current abilities of mql, especially memory management, smart pointers and so on. - Lots of work and lots of possibilities. But not very MQL-Like code anymore.

Jsut as a concept, to extend way beyond the capabilities of the (very limited) mql-compiler.

🤣 I think that would be just like creating an over-complicatd "Rube Goldberg" contraption, just to do such a simple thing. I would rather continue to stick to the the old "KISS" method! 🤣

Alain Verleyen
41742
Alain Verleyen  
It's just not possible.
Dominik Egert
1527
Dominik Egert  
Alain Verleyen:
It's just not possible.

It would take alot of effort to make it work properly, transparent and versatile. - But it is possible, including the (very anoing) limitation of the return values of functions.

Dominik Egert
1527
Dominik Egert  
Fernando Carreiro:

🤣 I think that would be just like creating an over-complicatd "Rube Goldberg" contraption, just to do such a simple thing. I would rather continue to stick to the the old "KISS" method! 🤣

Yes. that visualises the issue very good.