Features of the mql5 language, subtleties and tricks - page 98

 
TheXpert:

What's the point? To save a couple of bytes of memory? Especially with double you get different numbers (== will be false)

It makes no sense. I like this design, haven't seen it before.

 
fxsaber:

Doesn't make any sense. I like the design, haven't seen it before.

Ah, ok. xor is more elegant, imho.

 
TheXpert:

ah, okay. xor is more elegant, imho

I agree

#define  SWAP(A, B) { A ^= B; B ^= A; A ^= B; }


SZY

#define  SWAP(A, B) A ^= (B ^= (A ^= B));


From Wiki.

However, on modernCPUs the XOR technique is much slower than using a temporary variable for exchange. This is due to the parallelization of instruction execution. In the XOR technique, the operands of all commands depend on the results of previous commands, so they must be executed in strictly sequential order. It is recommended that you test the speeds of both alternatives on your target architecture on a case-by-case basis.

 
Nightmare.
 
fxsaber:

From Wiki

What if they paralleled the previous addition/subtraction? )

 
Taras Slobodyanik:

What if they paralleled previous additions/subtractions? )

A sequence-dependent algorithm does not parallelize.

An algorithm with a time variable is not, so it is parallelizable.

 
Nope...
 

Forum on trading, automated trading systems and trading strategies testing

Bugs, bugs, questions

Ilyas, 2016.08.24 11:08

The array ("inside") stores allocated - under how many elements the array is allocated.

The logic of working with allocated (conditional code):
ArrayResize(arr,int size,int reserve)
  {
   if(arr.allocated<size)
      if(!ArrayAllocateMemory(arr,size+reserve))  // -> arr.allocated=size+reserve;
         return(-1);
   //---
   CallConstructorsOrDestructors(arr,size);
   //---
   arr.size=size;
   return(size);
  }
 

The topic of today's program is template fever, or how to get rid of a template in the ass )

There is often a need to pass some variable as a template argument by reference to modify it, but the template specification, unfortunately, does not allow you to explicitly specify the non-constancy of the argument, as in normal functions:

void Modify(int&) { }  // Принимает только не константы

template<typename T>
void Modify(T& a) {  } // Принимает любые аргументы

This can cause inconvenience when the argument goes down the template chain to its destination, and there it turns out to be a constant and cannot be changed. And this error occurs somewhere in the depths of libraries. Finding out where the original template was called from is sometimes a very difficult task.

template<typename T>
void f0(T& a)  { a=10; }  // 'a' - constant cannot be modified

template<typename T>
void f1(T& a)  { f0(a); }

template<typename T>
void f2(T& a)  { f1(a); }

void Source() { const int a=0;  f2(a); }

This is not a problem in normal IDEs. For example VS has a full trace of the template path, so it is enough to click in the right place and it will take you right there. But MQL is in trouble. Which may become a constant headache for the template maker.

But it can be fixed. For this, you can use the template overloading:

template<typename T>
void Modify(const T&); // Фэйковый запрещённый шаблон

template<typename T>
void Modify(T& a) { a=10; }

Now, when you try to pass a constant, the upper template will be called. But this is an insufficient solution, because first, the error only occurs when compiling the executable (and in .mqh it is not), and second, this error occurs at the place where the template is declared, not at the place of its call, which we want to find. So let's move on.

In the case where the template is a method of the class, everything is simple: we place the fake template in a private section and get an access error when we try to call it.

In case of an ordinary function, it is more complicated. In C++ this problem cannot be solved by overloading only, additional functionality is required, which is absent in MQL. But here the powerful weapon of MQL - bugs - comes to our aid! ) In this case one of such bugs turns out to be very useful to us )
We add an additional parameter T2 to our fake template and now, when trying to call the wrong template, we get an error at the call place:

template<typename T, typename T2>
void Modify(const T&);  // Запрещаем

template<typename T>
void Modify(T& a) { a=10; }

void Source()
{ 
  int a, const b=0;
  Modify(a);  // всё ОК
  Modify(b);  // template mismatch
}

Problem solved. In C++ the bottom template will of course be called in both cases, because there's no such bug.

This method can be useful in one more case: if you need to explicitly control the types of function arguments, disabling the implicit conversion.
For example, the function should accept only the datetime argument, blocking all sorts of int's and other stuff.
We make a corresponding variant:

template<typename T, typename T2>
void MyFunc(T);  // Запрещаем

void MyFunc(datetime time) {  }

Now, as in the previous case, a compilation error will be thrown if you try to pass an unresolved type.

By the way, I always do such a ban for datetime. I think it was for nothing that the developers allowed implicit conversion to it at all and without any warnings to the compiler (except for long and string). Even any enum is freely cast to it without any warnings.

There is also the opposite problem: to forbid only a call of a certain type. The solution will be similar:

template<typename T,typename T2>
void MyFunc(datetime);  // Запрещаем

template<typename T>
void MyFunc(T arg) {  }


As mentioned above, everything inside the class is solved without extra parameters.

 
Alexey Navoykov:

Continuing our "dumb hands" column, today's topic is pattern fever, or how to rid yourself of the pattern in your ass.)

Often there is a need to pass some variable as a template argument by reference to modify it.

The need arises to pass by reference without modification - for speed, or an object.

But the existing C++ template specification, unfortunately, does not allow one to explicitly specify the non-constancy of an argument, as it is done in usual functions:

And this can cause inconvenience when the argument goes down the chain of templates to its destination, and there it turns out to be a constant and can't be changed. And this error occurs somewhere in the depths of libraries. Detecting where the original template was called from is sometimes a very difficult task.

Is there a real example in MQL5 when this problem occurs?

It is not a problem in normal IDEs. For example VS displays the full trace of the template route, so you just click in the right place and it will take you right there. But in MQL it is a real problem. Which may become a constant headache for the template maker.

But it can be fixed. For this, you can use the template overloading:

Now, when you try to pass a constant, the upper template will be called. But this is an insufficient solution, because first, the error only occurs when compiling the executable (and in .mqh it is not), and second, this error occurs at the place where the template is declared, not at the place of its call, which we want to find. So let's move on.

In the case where the template is a method of the class, everything is simple: we place the fake template in a private section and get an access error when we try to call it.

In the case of a normal function, however, it is more complicated. Syntactically in C++ this problem is not solvable at all, as far as I understood. However we are lucky that MQL is not C++ - it has bugs.)

We add an additional parameter T2 to our fake template and get an error at the call point when trying to call the wrong template:

Problem solved. In C++, of course, the bottom template will be called in both cases.

The real example of convenience is missing.

This method can also be useful in another case: when you need to explicitly control the types of function arguments, by disabling the implicit conversion.
For example, the function should accept only the datetime argument, blocking all sorts of int's and other stuff.
We make a corresponding variant:

Now, as in the previous case, a compilation error will be thrown when trying to pass an unauthorized type.

It seems to be used in MQL5 to the fullest extent, as soon as it was available. If I understand it correctly, it's a standard.

By the way, I always do such a ban for datetime. I think the developers shouldn't have allowed implicit conversion to it at all, and even without any warning to the compiler (except for long and string). Even any enum is freely cast to it without any warnings.

There is also the opposite problem: to forbid only a call of a certain type. The solution would be similar:

Experiencing the convenience that datetime behaves as it does now. When is the problem?


All in all a very good and useful post, Thanks!