Caratteristiche del linguaggio mql5, sottigliezze e tecniche - pagina 98

 
TheXpert:

A che scopo, per risparmiare un paio di byte di memoria? Soprattutto con il doppio si ottengono numeri diversi (== sarà falso).

Non ha senso. Mi piace questo costrutto, non l'ho mai visto prima.

 
fxsaber:

Non ha alcun senso. Mi piace il design, non l'ho mai visto prima.

Ah, ok. xor è più elegante, imho.

 
TheXpert:

Ah, ok. xor è più elegante, imho.

D'accordo

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


SZ

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


Da Wiki.

Tuttavia, sulleCPUmoderne la tecnica XOR è significativamente più lenta che usare una variabile temporanea per lo scambio. Questo è dovuto alla parallelizzazione dell'esecuzione delle istruzioni. Nella tecnica XOR, gli operandi di tutti i comandi dipendono dai risultati dei comandi precedenti, quindi devono essere eseguiti in ordine strettamente sequenziale. Si raccomanda di testare le velocità di entrambe le alternative sull'architettura di destinazione caso per caso.

 
Incubo.
 
fxsaber:

Da Wiki

e se l'addizione/sottrazione precedente è in parallelo? )

 
Taras Slobodyanik:

E se fossero in parallelo con l'addizione/sottrazione precedente? )

Un algoritmo dipendente dalla sequenza non si parallelizza.

Un algoritmo con una variabile temporale non lo è, quindi è parallelizzabile.

 
No...
 

Forum sul trading, sistemi di trading automatico e test di strategie di trading

Bug, bug, domande

Ilyas, 2016.08.24 11:08

L'array ("dentro") memorizza l'allocazione - sotto quanti elementi è allocato l'array.

La logica per lavorare con le allocazioni (codice condizionale):
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 la nostra rubrica "dilly-dallying", l'argomento di oggi è la febbre da template, o come liberarsi di un template su per il culo )

C'è spesso la necessità di passare qualche variabile come argomento di un template per riferimento per modificarlo, ma la specifica del template, purtroppo, non permette di specificare esplicitamente la non costanza dell'argomento, come nelle funzioni normali:

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

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

Questo può causare inconvenienti quando l'argomento scende lungo la catena dei template fino alla sua destinazione, dove risulta essere una costante e non può essere cambiato. E questo errore si verifica da qualche parte nelle profondità delle librerie. Individuare da dove è stato chiamato il template originale è a volte un compito molto difficile.

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

Non è un problema negli IDE normali. Per esempio VS ha una traccia completa del percorso del modello, quindi è sufficiente cliccare nel posto giusto e vi porterà proprio lì. Ma il problema con MQL è lo stesso. Il che può diventare un mal di testa costante per il creatore di modelli.

Ma si può aggiustare. Per farlo, potete usare l'overloading dei template:

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

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

Ora, quando si cerca di passare la costante, verrà chiamato il modello superiore. Ma questa non è una soluzione sufficiente, perché in primo luogo, l'errore si verifica solo quando si compila l'eseguibile (e in .mqh non lo è), e in secondo luogo, questo errore si verifica dove il modello è dichiarato, non dove viene chiamato, che vogliamo trovare. Quindi andiamo avanti.

Quando il modello è un metodo di una classe, tutto è semplice: mettiamo il falso modello in una sezione privata e otteniamo un errore di accesso quando proviamo a chiamarlo.

Nel caso di una funzione semplice è più complicato. In C++ il problema non può essere risolto con il solo sovraccarico, abbiamo bisogno di funzionalità aggiuntive, che sono assenti in MQL. Ma qui la potente arma di MQL - i bug - ci viene in aiuto! ) In questo caso uno di questi bug si rivela essere molto utile per noi )
Aggiungiamo un parametro aggiuntivo T2 al nostro modello falso e ora, quando si cerca di chiamare il modello sbagliato, si ottiene un errore al punto di chiamata:

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 risolto. In C++ il template inferiore sarà ovviamente chiamato in entrambi i casi, perché non c'è questo bug.

Questo metodo può essere utile in un altro caso: quando abbiamo bisogno di controllare esplicitamente i tipi di argomenti delle funzioni, disabilitando la conversione implicita.
Per esempio, la funzione dovrebbe accettare solo l'argomento datetime, sopprimendo tutti i tipi di int e altre cose.
Facciamo una variante corrispondente:

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

void MyFunc(datetime time) {  }

Ora, come nel caso precedente, verrà lanciato un errore di compilazione quando si cerca di passare un tipo non risolto.

A proposito, faccio sempre un simile divieto per datetime. Penso che sia stato per niente che gli sviluppatori hanno permesso una conversione implicita ad esso e senza alcun avvertimento al compilatore (tranne che per long e string). Anche qualsiasi enum è liberamente lanciato ad esso senza alcun avvertimento.

C'è anche il problema opposto: proibire solo una chiamata di un certo tipo. La soluzione sarebbe simile:

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

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


Come detto sopra, tutto all'interno della classe è risolto senza parametri inutili.

 
Alexey Navoykov:

Continuando con la nostra rubrica "mani vertiginose", l'argomento di oggi è la febbre da template, o come liberarsi di un template su per il culo )

Spesso si presenta la necessità di passare qualche variabile come argomento di un template per riferimento per modificarlo.

Si presenta la necessità di passare per riferimento senza modifica - per la velocità, o per un oggetto.

Tuttavia, la specifica esistente dei template C++ purtroppo non permette di specificare esplicitamente la non costanza di un argomento, come avviene nelle funzioni usuali:

E questo può causare inconvenienti quando l'argomento scende lungo la catena di modelli fino alla sua destinazione e lì risulta essere una costante e non può essere cambiato. E questo errore si verifica da qualche parte nelle profondità delle librerie. Rilevare da dove è stato chiamato il modello originale è a volte un compito molto difficile.

C'è un esempio reale in MQL5 in cui si verifica questo problema?

Non è un problema negli IDE normali. Per esempio VS visualizza la traccia completa del percorso del modello, quindi basta cliccare nel posto giusto e andrà direttamente a destinazione. Ma in MQL è un vero problema. Il che può diventare un mal di testa costante per il creatore di modelli.

Ma si può aggiustare. Per farlo, potete usare l'overloading dei template:

Ora, quando si cerca di passare la costante, verrà chiamato il modello superiore. Ma questa non è una soluzione sufficiente, perché in primo luogo, l'errore si verifica solo durante la compilazione dell'eseguibile (e in .mqh non lo è), e in secondo luogo, questo errore si verifica dove il modello è dichiarato, non dove viene chiamato, che vogliamo trovare. Quindi andiamo avanti.

Quando il modello è un metodo di una classe, tutto è semplice: mettiamo il falso modello in una sezione privata e otteniamo un errore di accesso quando proviamo a chiamarlo.

Nel caso di una funzione normale, però, è più complicato. Sintatticamente, questo problema non è affatto risolvibile in C++, per quanto ho capito. Ma siamo fortunati che MQL non è C++ - ci sono dei bug in esso (e in questo caso questi bug possono essere aggirati).

Aggiungiamo un parametro aggiuntivo T2 al nostro falso template e otteniamo un errore al punto di chiamata quando cerchiamo di chiamare il template sbagliato:

Problema risolto. In C++ il template inferiore sarà chiamato in entrambi i casi, ovviamente.

Manca il vero esempio di convenienza.

Questo metodo può essere utile in un altro caso: quando abbiamo bisogno di controllare esplicitamente i tipi degli argomenti della funzione, disabilitando la conversione implicita.
Per esempio, la funzione deve accettare solo l'argomento datetime, escludendo tutti i tipi di int e altre cose.
Facciamo una variante corrispondente:

Ora, come nel caso precedente, verrà lanciato un errore di compilazione quando si cerca di passare un tipo non risolto.

Sembra essere usato in MQL5 al massimo, non appena è apparsa la possibilità. Se ho capito bene, è uno standard.

A proposito, faccio sempre un simile divieto per datetime. Penso che gli sviluppatori non avrebbero dovuto permettere la conversione implicita ad esso, e anche senza alcun avvertimento al compilatore (tranne che per long e string). Anche qualsiasi enum è liberamente lanciato ad esso senza alcun avvertimento.

C'è anche il problema opposto: proibire solo una chiamata di un certo tipo. La soluzione sarebbe simile:

Sperimentare la comodità di datetime che si comporta come ora. Quando è il problema?


Tutto sommato un post molto buono e utile, grazie!

Motivazione: