Características del lenguaje mql5, sutilezas y técnicas - página 98

 
TheXpert:

¿Para qué? ¿Para ahorrar un par de bytes de memoria? Especialmente con el doble se obtienen números diferentes (== será falso).

No tiene sentido. Me gusta esta construcción, no la había visto antes.

 
fxsaber:

No tiene ningún sentido. Me gusta el diseño, no lo había visto antes.

Ah, ok. xor es más elegante, imho.

 
TheXpert:

Ah, ok. xor es más elegante, imho.

De acuerdo

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


SZ

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


De Wiki.

Sin embargo, en lasCPUs modernas la técnica XOR es significativamente más lenta que el uso de una variable temporal para el intercambio. Esto se debe a la paralelización de la ejecución de instrucciones. En la técnica XOR, los operandos de todos los comandos dependen de los resultados de los comandos anteriores, por lo que deben ejecutarse en orden estrictamente secuencial. Se recomienda probar las velocidades de ambas alternativas en su arquitectura de destino en cada caso.

 
Una pesadilla.
 
fxsaber:

De la Wiki

¿qué pasa si la suma/resta anterior es paralela? )

 
Taras Slobodyanik:

¿Y si fueran paralelos a la suma/resta anterior? )

Un algoritmo dependiente de la secuencia no se paraleliza.

Un algoritmo con una variable temporal no lo es, por lo que es paralelizable.

 
No...
 

Foro sobre trading, sistemas de trading automatizados y pruebas de estrategias de trading

Bichos, errores, preguntas

Ilyas, 2016.08.24 11:08

El array ("inside") almacena el asignado - bajo cuántos elementos está asignado el array.

La lógica para trabajar con asignados (código condicional):
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);
  }
 

Siguiendo con nuestra columna de "tonterías", el tema de hoy es la fiebre de las plantillas, o cómo librarse de una plantilla por el culo )

A menudo es necesario pasar alguna variable como argumento de la plantilla por referencia para modificarla, pero la especificación de la plantilla, por desgracia, no permite especificar explícitamente la no-constancia del argumento, como en las funciones normales:

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

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

Esto puede causar inconvenientes cuando el argumento desciende por la cadena de plantillas hasta su destino, donde resulta ser una constante y no se puede cambiar. Y este error se produce en algún lugar de las profundidades de las bibliotecas. Detectar desde dónde se llamó a la plantilla original es a veces una tarea muy difícil.

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); }

No es un problema en los IDEs normales. Por ejemplo, VS tiene un trazado completo de la ruta de la plantilla, por lo que basta con hacer clic en el lugar correcto y te llevará allí, pero es un problema en MQL. Lo que puede convertirse en un constante dolor de cabeza para el creador de la plantilla.

Pero se puede arreglar. Para ello, puede utilizar la sobrecarga de plantillas:

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

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

Ahora, al intentar pasar la constante, se llamará a la plantilla superior. Pero esto no es una solución suficiente, porque en primer lugar, el error sólo se produce al compilar el ejecutable (y en el .mqh no es así), y en segundo lugar, este error se produce donde se declara la plantilla, no donde se llama, que es lo que queremos encontrar. Así que vamos a seguir adelante.

Cuando la plantilla es un método de una clase, todo es sencillo: colocamos la plantilla falsa en una sección privada y obtenemos un error de acceso cuando intentamos llamarla.

En el caso de una función simple es más complicado. En C++ el problema no se puede resolver sólo con la sobrecarga, necesitamos una funcionalidad adicional, que está ausente en MQL. Pero aquí la poderosa arma de MQL - los errores - viene en nuestra ayuda! ) En este caso, uno de estos errores resulta ser muy útil para nosotros )
Añadimos un parámetro adicional T2 a nuestra plantilla falsa y ahora, al intentar llamar a la plantilla equivocada, obtenemos un error en el punto de llamada:

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
}

Problema resuelto. En C++ se llamará, por supuesto, a la plantilla inferior en ambos casos, porque no existe ese error.

Este método puede ser útil en un caso más: cuando necesitamos controlar explícitamente los tipos de argumentos de las funciones, desactivando la conversión implícita.
Por ejemplo, la función debería aceptar sólo el argumento datetime, suprimiendo todo tipo de int's y otras cosas.
Hacemos una variante correspondiente:

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

void MyFunc(datetime time) {  }

Ahora, como en el caso anterior, se lanzará un error de compilación al intentar pasar un tipo no resuelto.

Por cierto, siempre hago una prohibición de este tipo para datetime. Creo que para nada los desarrolladores permitieron una conversión implícita a la misma y sin ninguna advertencia al compilador (excepto para long y string). Incluso cualquier enum se puede lanzar libremente a él sin ninguna advertencia.

También existe el problema contrario: prohibir sólo una llamada de un determinado tipo. La solución sería la misma:

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

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


Como se mencionó anteriormente, todo dentro de la clase se resuelve sin parámetros innecesarios.

 
Alexey Navoykov:

Siguiendo con nuestra columna de "manos vertiginosas", el tema de hoy es la fiebre de las plantillas, o cómo librarse de una plantilla por el culo )

A menudo surge la necesidad de pasar alguna variable como argumento de la plantilla por referencia para modificarla.

Surge la necesidad de pasar por referencia sin modificación - para la velocidad, o un objeto.

Sin embargo, la especificación actual de las plantillas de C++ lamentablemente no permite especificar explícitamente la no-constancia de un argumento, como ocurre en las funciones habituales:

Y esto puede causar inconvenientes cuando el argumento baja por la cadena de patrones hasta su destino y allí resulta ser una constante y no se puede cambiar. Y este error se produce en algún lugar de las profundidades de las bibliotecas. Detectar desde dónde se llamó al patrón original es a veces una tarea muy difícil.

¿Hay algún ejemplo real en MQL5 en el que se produzca este problema?

No es un problema en los IDEs normales. En VS, por ejemplo, se muestra el trazado completo de la ruta de la plantilla, por lo que basta con hacer clic en el lugar correcto y te llevará allí, pero en MQL es un verdadero problema. Lo que puede convertirse en un constante dolor de cabeza para el creador de la plantilla.

Pero se puede arreglar. Para ello, puede utilizar la sobrecarga de plantillas:

Ahora, al intentar pasar la constante, se llamará a la plantilla superior. Pero esto no es una solución suficiente, porque en primer lugar, el error sólo se produce al compilar el ejecutable (y en el .mqh no es así), y en segundo lugar, este error se produce donde se declara la plantilla, no donde se llama, que es lo que queremos encontrar. Así que vamos a seguir adelante.

Cuando la plantilla es un método de una clase, todo es sencillo: colocamos la plantilla falsa en una sección privada y obtenemos un error de acceso cuando intentamos llamarla.

En el caso de una función normal, sin embargo, es más complicado. Sintácticamente, este problema no se puede resolver en absoluto en C++, hasta donde he entendido. Pero tenemos la suerte de que MQL no es C++ - hay errores en él ) Y en este caso estos errores pueden ser manejados de la mejor manera )

Añadimos un parámetro adicional T2 a nuestra plantilla falsa y obtenemos un error en el punto de llamada al intentar llamar a la plantilla equivocada:

Problema resuelto. En C++ se llamará a la plantilla inferior en ambos casos, por supuesto.

Falta el verdadero ejemplo de conveniencia.

Este método puede ser útil en un caso más: si necesita controlar explícitamente los tipos de los argumentos de la función, desactivando la conversión implícita.
Por ejemplo, la función debe aceptar sólo el argumento datetime, bloqueando todo tipo de int's y otras cosas.
Hacemos una variante correspondiente:

Ahora, como en el caso anterior, se lanzará un error de compilación al intentar pasar un tipo no resuelto.

Parece que se utiliza en MQL5 al máximo, en cuanto apareció la posibilidad. Si lo he entendido bien, es una norma.

Por cierto, siempre hago una prohibición de este tipo para datetime. Creo que los desarrolladores no deberían haber permitido la conversión implícita a la misma, e incluso sin ninguna advertencia al compilador (excepto para long y string). Incluso cualquier enum se puede lanzar libremente a él sin ninguna advertencia.

También existe el problema contrario: prohibir sólo una llamada de un tipo determinado. La solución sería similar:

Experimentar la conveniencia de que el datetime se comporte como lo hace ahora. ¿Cuándo es el problema?


En definitiva, un post muy bueno y útil, ¡gracias!