Características da linguagem mql5, subtilezas e técnicas - página 98

 
TheXpert:

Para salvar alguns bytes de memória? Especialmente com o dobro você recebe números diferentes (== será falso).

Não tem sentido. Eu gosto desta construção, nunca a tinha visto antes.

 
fxsaber:

Não faz sentido nenhum. Eu gosto do desenho, nunca o vi antes.

Ah, ok. O Xor é mais elegante, imho.

 
TheXpert:

Ah, ok. O Xor é mais elegante, imho.

Concordo

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


SZ

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


Da Wiki.

No entanto, nasCPUsmodernas, a técnica XOR é significativamente mais lenta do que a utilização de uma variável temporária para troca. Isto é devido à paralelização da execução das instruções. Na técnica XOR, os operandos de todos os comandos dependem dos resultados dos comandos anteriores, pelo que devem ser executados em ordem estritamente sequencial. É recomendado que você teste as velocidades de ambas as alternativas em sua arquitetura de destino, caso a caso.

 
Pesadelo.
 
fxsaber:

Do Wiki

E se a adição/subtracção anterior for paralela? )

 
Taras Slobodyanik:

E se eles se assemelhassem à adição/subtracção anterior? )

Um algoritmo dependente da sequência não faz paralelo.

Um algoritmo com uma variável temporal não é, por isso é paralelizável.

 
Não...
 

Fórum sobre negociação, sistemas de negociação automatizados e testes de estratégia de negociação

Bugs, bugs, perguntas

Ilyas, 2016.08.24 11:08

O array ("dentro") armazena o alocado - sob quantos elementos o array é alocado.

A lógica para trabalhar com alocados (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);
  }
 

Continuando a nossa coluna "dilly-dallying", o tópico de hoje é a febre do template, ou como se livrar de um template pelo cu acima )

Existe frequentemente a necessidade de passar alguma variável como argumento de modelo por referência para a modificar, mas a especificação do modelo, infelizmente, não permite especificar explicitamente a não constância do argumento, como nas funções normais:

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

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

Isto pode causar inconvenientes quando o argumento desce a cadeia do template até ao seu destino, onde acaba por ser uma constante e não pode ser alterado. E este erro ocorre algures nas profundezas das bibliotecas. Detectar de onde foi chamado o template original é, por vezes, uma tarefa muito 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); }

Não é um problema em IDEs normais. Por exemplo, a VS tem um rastreamento completo da rota do modelo, então é suficiente clicar no lugar certo e ele o levará até lá. Mas é um problema na MQL. O que pode tornar-se uma dor de cabeça constante para o criador do modelo.

Mas pode ser consertado. Para isso, você pode usar a sobrecarga do modelo:

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

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

Agora, ao tentar passar a constante, o modelo superior será chamado. Mas esta não é uma solução suficiente, porque em primeiro lugar, o erro só ocorre quando compilamos o executável (e em .mqh não é), e em segundo lugar, este erro ocorre onde o template é declarado, não onde é chamado, o que queremos encontrar.

Quando o template é um método de uma classe, tudo é simples: colocamos o template falso em uma seção privada e obtemos um erro de acesso quando tentamos chamá-lo.

No caso de uma função simples é mais complicado. Em C++ o problema não pode ser resolvido apenas com sobrecarga, precisamos de funcionalidades adicionais, que estão ausentes no MQL. Mas aqui a poderosa arma do MQL - os bugs - vem em nosso auxílio! ) Neste caso um desses bugs acaba sendo muito útil para nós )
Adicionamos um parâmetro adicional T2 ao nosso template falso e agora, quando tentamos chamar o template errado, obtemos um erro no ponto de chamada:

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 resolvido. Em C++ o modelo inferior será, naturalmente, chamado em ambos os casos porque não existe tal bug lá.

Este método pode ser útil em mais um caso: quando precisamos controlar explicitamente os tipos de argumentos da função, desativando a conversão implícita.
Por exemplo, a função deve aceitar apenas o argumento da data, suprimindo todo o tipo de int e outras coisas.
Nós fazemos uma variante correspondente:

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

void MyFunc(datetime time) {  }

Agora, como no caso anterior, um erro de compilação será lançado ao tentar passar um tipo não resolvido.

A propósito, eu sempre faço tal proibição por data. Eu acho que foi por nada que os desenvolvedores permitiram uma conversão implícita para ela e sem nenhum aviso ao compilador (exceto por longo e string). Mesmo qualquer enumeração é livremente lançada a ele sem qualquer aviso.

Há também o problema oposto: proibir apenas uma chamada de um determinado tipo. A solução seria a mesma:

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

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


Como mencionado acima, tudo dentro da classe é resolvido sem parâmetros desnecessários.

 
Alexey Navoykov:

Continuando com a nossa coluna "mãos tontas", o tópico de hoje é a febre do modelo, ou como se livrar de um modelo pelo cu acima )

Muitas vezes surge a necessidade de passar alguma variável como um argumento modelo por referência para modificá-la.

Surge a necessidade de passar por referência sem modificações - por velocidade, ou por um objeto.

No entanto, a especificação do modelo C++ existente infelizmente não permite que a não constância de um argumento seja especificada explicitamente, como acontece nas funções habituais:

E isso pode causar inconvenientes quando o argumento desce a cadeia do padrão até o seu destino e lá ele se revela uma constante e não pode ser alterado. E esse erro ocorre em algum lugar nas profundezas das bibliotecas. Detectar de onde o modelo original foi chamado é às vezes uma tarefa muito difícil.

Existe um exemplo real na MQL5 quando este problema ocorre?

Não é um problema em IDEs normais. Por exemplo, o VS mostra o traçado completo da rota do modelo, então basta clicar no local certo e ele irá direto para o destino. Mas no MQL é um problema real. O que pode tornar-se uma dor de cabeça constante para o criador do modelo.

Mas pode ser arranjado. Para isso, você pode usar a sobrecarga do modelo:

Agora, ao tentar passar a constante, o modelo superior será chamado. Mas esta não é uma solução suficiente, porque em primeiro lugar, o erro só ocorre quando compilamos o executável (e em .mqh não é), e em segundo lugar, este erro ocorre onde o template é declarado, não onde é chamado, o que queremos encontrar.

Quando o template é um método de uma classe, tudo é simples: colocamos o template falso em uma seção privada e obtemos um erro de acesso quando tentamos chamá-lo.

No caso de uma função normal, no entanto, é mais complicado. Sintaticamente, este problema não é de todo resolúvel em C++, tanto quanto eu entendi. Mas temos sorte que o MQL não é C++ - há bugs nele ) E, neste caso, esses bugs podem ser trabalhados por aí).

Nós adicionamos um parâmetro adicional T2 ao nosso modelo falso e obtemos um erro no ponto de chamada quando tentamos chamar o modelo errado:

Problema resolvido. Em C++ o modelo inferior será chamado em ambos os casos, é claro.

O verdadeiro exemplo de conveniência está faltando.

Este método pode ser útil em mais um caso: quando precisamos de controlar explicitamente os tipos de argumentos da função, desactivando a conversão implícita.
Por exemplo, a função deve aceitar apenas o argumento da data, bloqueando todo o tipo de int's e outras coisas.
Nós fazemos uma variante correspondente:

Agora, como no caso anterior, um erro de compilação será lançado ao tentar passar um tipo não resolvido.

Parece ser usado na MQL5 em toda a sua extensão, assim que a possibilidade apareceu. Se eu entendi bem, é um padrão.

A propósito, eu sempre faço tal proibição por data. Eu acho que os desenvolvedores não deveriam ter permitido a conversão implícita para ele, e mesmo sem qualquer aviso ao compilador (exceto por longo e string). Mesmo qualquer enumeração é livremente lançada a ele sem qualquer aviso.

Há também o problema oposto: proibir apenas uma chamada de um determinado tipo. A solução seria semelhante:

Experimentando a conveniência de se comportar como agora. Quando é o problema?


Em suma, um post muito bom e útil. Obrigado!