Bug: Base class disables type checking

 
This one caught me off guard when dealing with generic iterators, the minimum code to reproduce the bug:

#property copyright ""
#property link ""
#property version "1.00"
#property strict

#property indicator_chart_window
#property indicator_buffers 0
#property indicator_plots 0

class Base{};

class A : public Base{};

class B : public Base{};

int OnInit() {
  A a;

  // This line should not compile since the types are different but it does and
  // calls the B’s default constructor as if nothing was being assigned to it.
  B b = a; 

  return INIT_SUCCEEDED;
}

int OnCalculate(
  int const TOTAL,
  int const CALCULATED,
  datetime const & TIME[],
  double const & OPEN[],
  double const & HIGH[],
  double const & LOW[],
  double const & CLOSE[],
  long const & TICK_VOLUME[],
  long const & VOLUME[],
  int const & SPREAD[]
) {
  return TOTAL;
}
 
If I understand this correctly, it's correct behavior.

B gets assigned the "remainings" of A, since they share the same base class.

But you are missing constructors to deal with such a situation.
 
Dominik Egert #:
If I understand this correctly, it's correct behavior.

B gets assigned the "remainings" of A, since they share the same base class.

But you are missing constructors to deal with such a situation.
No it's wrong, A and B are different types, remove the base class and it'll detect the error.


The only situation for B to be assigned with A is if it has a constructor or overload of the assignment operator accepting A as follows:

class B : public Base{
public:
  B(){}
  B(A&){}
  void operator=(A&){}
};

Another way to think of that assignment is what the compiler normally does, since it is initializing the object, it passes the value from assignment
to a constructor:

B b = a;
// It technically converts the previous line to a constructor call.
B b(a);

But in that specific case, it is ignoring the value in the assignment and just calling B's default constructor.
 
Updated my posts, it is hapenning even on non generic classes.
 
I get your point, though as it seems, if I understand that correct, it is c++ normal behavior.


Although, I am not sure.
 
Dominik Egert #:
I get your point, though as it seems, if I understand that correct, it is c++ normal behavior.


Although, I am not sure.
C++ detect correctly the lack of constructor/overload and generate an error, try the following on REPL:

class Base{};

class A : public Base{};

class B : public Base{};

int main() {
  A a;
  B b = a; 
  return 0;
}
It will show the error:
clang++-7 -pthread -std=c++17 -o main main.cpp
main.cpp:9:5: error: no viable conversion from 'A' to 'B'
  B b = a; 
    ^   ~
main.cpp:5:7: note: candidate constructor (the implicit copy
      constructor) not viable: no known conversion from 'A' to
      'const B &' for 1st argument
class B : public Base{};
      ^
main.cpp:5:7: note: candidate constructor (the implicit move
      constructor) not viable: no known conversion from 'A' to 'B &&'
      for 1st argument
class B : public Base{};
      ^
1 error generated.
exit status 1

At first I thought MQL5 was generating an implicit copy constructor, which would not be great either, but no, it calls the default constructor
and ignores the value assigned as if nothing was being passed.
 
Well, I guess you really found an error.
As I said, you are missing the constructor.

OO has really some shady implementation limits in MQL. I do my best to stay away from it. I get so many issues with it all the time.

I definitely need to begin coding real c/c++ again. I notice, I am beginning to loose my perception for it.

Next year, I will write myself a complete mql 5 c/c++ API interface, so I can finally code with real power again.

After all, it doesn't take to much to make the API available through a service and a generic EA to do all the coding in original c/c++.

It won't be for the markets, of course, but for internal use or personal use it should be good.
 
Dominik Christian Egert #:
Well, I guess you really found an error.
As I said, you are missing the constructor.

That's exactly the point, if I didn't write a constructor in B to accept A, it means I don't want the code "B b = a" to compile,
this is why C++ shows this error. Errors like this are useful when the code base gets large.

If you remove the base class, MQL is able to to perform this check, so it should show an error in this case also.

This bug can really caught me off guard when I was refactoring some code, at one point I mixed a generic list iterator with an
array iterator, the indicator compiled fine but it just didn't work, thank God I am using git to manage the source code so it
took only minutes to isolate issue.

I don't know if this bug is only in recent builds(I am using the latest beta) but it does happen in MT4 also.
 
Dominik Christian Egert #:
OO has really some shady implementation limits in MQL. I do my best to stay away from it. I get so many issues with it all the time.

Don't be discoraged by it, recommend you try the generics too, it still an awesome language and it is the only platform that allowed me to
write pretty complex stuff. I am hoping it'll have other C++'s features like returning references and exceptions. Just have to be aware
of some quirks of the compiler.

 
Thank you. I've written about 8MB of code for MQL over the last 15 months. I use extensively templates and structs, but most of my code is procedural. Data handling is OO.

Sti the limits of the language, compared with c++ are enormous. Although the API is quite nice.

Still, for a trading product, its very powerful. I don't know of any other product with such a sophisticated and fast language. And I hate java.


 
Dominik Christian Egert #:
And I hate java.

I share this feelling, being forced to always use classes was a bad design decision. I personally like to mix procedural and OO too, whatever seams easier.