[CLOSED] : Compiler bug with template parameter = void* - page 6

 
Alexey Navoykov:

Everything is working fine, why are you making this up?

In the log we get:

void A::~A()
void B::~B()

Why did I even fall for it...

Well then I'm sorry, didn't know you could do that, MKL is a lot different than C++. On the plus side, removing void* is UB.

 

Forum on trading, automated trading systems and trading strategy testing

New version of MetaTrader 5 build 1930: Floating Chart Window and .Net Library in MQL5

Alexey Navoykov, 2018.12.15 02:44

Dear Developers. Earlier in one of the threads we discussed the compiler defect that allows implicit casting of a base class to a derived class, but it seems to have remained unnoticed by you. This is a serious problem, making error checking difficult and becomes a constant headache when actively using OOP. Such casting should be only explicit. This is a general rule for both C++ and C#.

class A {  };

class B : public A { };

A* a = new A;

B* b = a;  // Нет ошибки компиляции!

void f(B*) {  }

void OnInit()
{ 
  f(a);  // Нет ошибки компиляции!
}  

And what to do here?

class A {  };

class B : public A { };

A* a = new A;

void* v = a;

B* b = v;  // Нет ошибки компиляции!


Should this behavior be considered an error too?

 
Alexey Navoykov:

If the styler makes the code hard to read, then why the hell use it?

For me, a styler is good only when ALL its rules can be flexibly customized.

So, if you read someone else's code in a printer-printed form (or on a forum, like here).

 
fxsaber:
About parentheses
((A*)(b.GetPtr())).f(); // Доп. скобки, чтобы подчеркнуть, что именно имелось в виду, не полагаясь на приоритеты.

Well, maybe it will emphasize you, but for me it will only confuse. But looking at this expression, I can't immediately understand whose method is being called here. But in the previous two lines, it's clear at once.

To understand what is being done you should open all the parentheses. The more parentheses there are, the more time is wasted on figuring out what is going on, especially if they are not separated by spaces.

 
Alexey Navoykov:

Well, maybe it will emphasize you, but for me it will only confuse. But looking at this expression, I cannot immediately understand whose method is called here. But in the previous two lines, everything is clear at once.

To understand exactly what is being done, you have to open up all the brackets. The more brackets - the more time is spent on understanding what is going on. Especially if they are not separated by spaces in any way.

Additional parentheses are not for reading - let the styler take care of that, putting spaces.

But for self-control while writing. Why should I rely on someone's priorities when writing in a sensitive area, while being aware that I am writing cross-platform code (and not necessarily only MT4/5) that can be ported to other languages? The additional brackets completely eliminate the influence of language priorities. Everything becomes absolutely unambiguous. Because of this there is a 100% reliability that nothing will fail in this place after the next build.


Moreover, when I'll read this bracket hell, I'll have to spend time on absolute understanding of exactly what I mean here. And on the subject of visibility.

bool a = (1 < 2) && (3 < 4);
bool b = 1 < 2 && 3 < 4;

let's ask, which option is more visual?

 
fxsaber:

Does this behaviour also count as a mistake?

Of course it does. This is the same thing.

So it turns out that nothing is generated where a problem is really possible and at least warnings are required (or even a compilation error). But they don't spare any warnings when brackets are forced on us ) And some people here even propose to prohibit compilation without brackets and threaten us with smackheads ) That's how we live...

 
Alexey Navoykov:

Of course. This is the same thing.

So it turns out that if there is a real problem and at least a warning is required (or even a compilation error), nothing is shown. But with brackets they don't spare any warnings ) And some people here even propose to prohibit compilation without brackets and threaten to smack you around ) That's how we live...

So you need a warning too? What kind of double standard is that: in both places behavior is unambiguous, but with brackets you are against warnings, and here you are for it?

You need a warning so you don't make hard-to-find mistakes. So difficulty is a subjective assessment. So with brackets you don't make mistakes, and here you can. And for me it's vice versa.

So which one of us should the rules for issuing warnings be adjusted to?

 
Ilya Malev:

I didn't know about StringConcatenate, it's a pity that in MT5 it was redesigned and cannot be used without string s. And the StringFormat is much faster on 4

And in general for some reason this operation of "polling" a pointer through a string is almost twice slower in 5, although in general it works faster there, sometimes by an order

it's possible that StringConcatenate() is 32 bit, you don't know, the developers have already written that metaetiters in 5 and 4 are the same, maybe because of compatibility they "wrapped" it

Yesterday I tried to solve your problem with dynamic_cast< >. The problem is that MQL do not allow to dereference pointers. the function in a class method can be called via dynamic_cast<C_myclass >( func( ) ), you can get a pointer to the class via dynamic_cast< > but what to do with a pointer? - you can reassign void *ptr , but there is no sense because the pointer cannot be dereferenced anyway

 
pavlick_:

If you want to scrap CArayObject, you have to make an override (like this https://www.mql5.com/ru/forum/170952/page110#comment_9894796) over the base class and put them in an array (possibly yours), but then you won't need void* anymore.

I'm not against void*, it's needed, but in a different capacity.

I don't see the point of code by reference (although I don't use standard libraries either). If putting an object into an array involves creating a copy of it, then the assignment method or copy constructor must be declared and described explicitly in that class, otherwise no wrappers will help anyway. If you only need to put a reference to an object into an array, you don't need any wrappers at all (why?).

By the way, you seem not to know that if(p) delete p is not identical to "if reference points to an existing dynamic object, delete it" in mql.

class A{};

void OnStart()
 {
  A *a=new A;
  if(a) Print("Кукареку!");
  if(CheckPointer(a)==POINTER_DYNAMIC) Print("Динамический объект существует и может быть удален");
  else                                 Print("Объект не существует, либо он автоматический");
  delete a;
  if(a) Print("Кукареку!");
  if(CheckPointer(a)==POINTER_DYNAMIC) Print("Динамический объект существует и может быть удален");
  else                                 Print("Объект не существует, либо он автоматический");
 }
 
fxsaber:

And on the subject of visibility.

let's ask, which one is clearer?

Well, if that's how the styler formatted it for you :

1 < 2 && 3 < 4;

then, again, it's up to the stylist. I would never do this in my code. I would do it this way:

1<2 && 3<4
либо
1 < 2  &&  3 < 4