Libreria di classi generiche - bug, descrizione, domande, caratteristiche d'uso e suggerimenti - pagina 24

 
fxsaber:

Domanda su come ottenere un valore da una chiave. Nel codice della libreria, questo metodo si presenta così

//+------------------------------------------------------------------+
//| Find index of entry with specified key.                          |
//+------------------------------------------------------------------+
template<typename TKey,typename TValue>
int CHashMap::FindEntry(TKey key)
  {
   if(m_capacity!=NULL)
     {
      //--- get hash code from key
      int hash_code=m_comparer.HashCode(key)&0x7FFFFFFF;
      //--- search pair with specified key
      for(int i=m_buckets[hash_code%m_capacity]; i>=0; i=m_entries[i].next)
         if(m_entries[i].hash_code==hash_code && m_comparer.Equals(m_entries[i].key,key))
            return(i);
     }
   return(-1);
  }

Sì, questo codice può essere fuorviante a causa della riassegnazione non standard di i in for.

Prima accediamo al sub-array per il suo indice, che può contenere il nostro valore:i=m_buckets[hash_code%m_capacity];(cioè i indice del sub-array o bin valore).

Poi, nello stesso for, l'indice del contenitore viene trasformato nell'indice dell'elemento del contenitore:i=m_entries[i].next

In effetti, il codice è scritto correttamente, perché in un caso tipico ogni sub-array avrà in media un elemento e il ciclo sarà in media eseguito solo una volta.

 
Vasiliy Sokolov:

Sì, questo codice può essere fuorviante a causa della riassegnazione non standard di i in for.

In primo luogo, accediamo a un sub-array per il suo indice, che può contenere il nostro valore:i=m_buckets[hash_code%m_capacity];(cioè i indice del sub-array o paniere di valori).

Poi, nello stesso for, l'indice del contenitore viene trasformato nell'indice dell'elemento del contenitore:i=m_entries[i].next

In effetti, il codice è scritto correttamente perché in un caso tipico ogni sub-array conterrà in media un elemento e il ciclo verrà eseguito in media solo una volta.

Ho capito che il ciclo è fatto per le collisioni: per passare attraverso la mini-lista.

 
fxsaber:

Immagino che il ciclo sia fatto per le collisioni: per passare attraverso una mini-lista.

Sì, assolutamente giusto.

 

Ha usato la libreria dei modelli(CArrayList) per memorizzare i tipi personalizzati. L'impressione non è grande. Per comodità ho scritto delle macro

#define  CLEANUP   do {                                      \
   for(int i_cln = 0;  i_cln < segs.Count();  ++ i_cln) {   \
      Wave_end *cln_el;                                     \
      if(  segs.TryGetValue(i_cln, cln_el) )                \
         delete cln_el;                                     \
   }}while(false)
#define  SSEG(IND)  do {                \
if( ! segs.TryGetValue(IND, we) ) {    \
   CLEANUP;                            \
   continue;                           \
}}while(false)

L'eccessiva infallibilità in TryGetValue + l'impossibilità di passare le classi per valore rende l'uso penoso.

 
I commenti non relativi a questo argomento sono stati spostati in "Domande dai principianti di MQL5 MT5 MetaTrader 5".
 

Ditemi, forse non capisco qualcosa, ma se cerco di usare una costruzione di questo tipo:

#include <Generic\\ArrayList.mqh>

struct Option {
   string name;
   color  clr;
};

...

CArrayList<Option> _options;

Ricevo un errore:

'Option' - gli oggetti sono passati solo per riferimento ICollection.mqh 14 18

E poi c'è tutta una serie di errori...
 
Andrey Pogoreltsev:

Ditemi, forse non capisco qualcosa, ma se cerco di usare una costruzione di questo tipo:

Ricevo un errore:

'Option' - gli oggetti sono passati solo per riferimento ICollection.mqh 14 18

e dopo c'è un'intera pila di errori...

Prova così:

#include <Generic\\ArrayList.mqh>

class Option {
   string name;
   color  clr;
};

...

CArrayList<Option*> _options;
 
Sergey Eremin:

Prova in questo modo:

Passare/memorizzare puntatori a una collezione è sbagliato concettualmente.

 
Andrey Pogoreltsev:

Passare/memorizzare puntatori a una collezione è sbagliato concettualmente.

Non c'è nessun generico per MQL che sia anche solo marginalmente adatto. tutti loro hanno seri bug. usate un array integrato, vi darà meno mal di testa.

 
TheXpert:

Non c'è nessun generico per MQL che sia anche solo leggermente adatto. tutti loro hanno seri bug. usate un array incorporato, vi darà meno mal di testa.

Beh, sì, ho usato un array. Perché creare collezioni e metterle in kodobase se sono adatte solo ai tipi incorporati?)