Biblioteca de clases genéricas - errores, descripción, preguntas, características de uso y sugerencias - página 29

 
Alexey Volchanskiy:

MSDN lo llama ring buffer, no se me ocurrió el nombre.

enlace a la

Alexey Navoykov:

...y terminando con una conversión a argumentos por referencia, no sólo por valor.

puede haber un problema con los literales

 
TheXpert:

enlace en el estudio

Puede haber un problema con los literales

Me da pereza volver a buscar ese artículo, pero lo he estirado un poco. Una lista enlazada simple o doble se basa en una lista enlazada, pero el último elemento almacena un enlace con el primero.

 
TheXpert:

puede haber problemas con los literales

No, tengo la clase "valores" heredada de la clase base "referencia", puramente como una envoltura. Por lo tanto, sólo hay que seleccionar la versión requerida de la clase e ir
 
Alexey Volchanskiy:

Una lista enlazada simple o doble se basa en una lista enlazada, pero el último elemento de la lista enlazada almacena un enlace con el primer elemento.

Esa es la cuestión: es una "base", no una sustitución. Nadie ha impedido que los desarrolladores la conviertan también en un contenedor adicional. En lugar de sustituir los conceptos comunes
 
Alexey Navoykov:

Lo más probable es que quien haya portado estas clases haya decidido simplificarse la vida simplificando el código. En lugar de dos punteros m_first y m_last hizo un solo puntero m_head...

La clase LinkedList está correctamente portado, sólo hay una cabeza de puntero, que es tanto el inicio como el final. Así que la implementación interna es efectivamente un bucle, pero el comportamiento externo no lo es. MQ tiene un error en la clase CLinkedNode (métodos Next y Previous). Aquí está el aspecto de su implementación original:

        public LinkedListNode<T>? Next
        {
            get { return next == null || next == list!.head ? null : next; }
        }

        public LinkedListNode<T>? Previous
        {
            get { return prev == null || this == list!.head ? null : prev; }
        }

Y así es como se traslada a MQL:

   CLinkedListNode<T>* Next(void)                      { return(m_next); }
   CLinkedListNode<T>* Previous(void)                  { return(m_prev); }

Tal vez no estuvieron atentos y se equivocaron.

Pero en general también me sorprende un poco la implementación de dotnet. Por qué no era posible hacer dos punteros en la propia lista (el primero y el último) en lugar de una cabeza. Eso evitaría comprobaciones extra en los métodos anteriores de la lista de nodos, es decir, se verían exactamente igual que MQ ahora, pero todo funcionaría correctamente. Por supuesto, ralentizaría un poco el proceso de inserción/borrado de nodos, pero aceleraría la iteración sobre ellos, que es una prioridad mucho mayor. Siguiente y Anterior son definitivamente llamados más a menudo, que los nodos añadidos. Así es como lo hice, pensé que sería lo mismo para melkomsoft. Pero no importa )

Por cierto, MQ tiene otro error en la implementación de CLinkedListNode y CRedBlackTreeNode. (excepto m_value) están pensados para ser cambiados únicamente por la propia clase de lista. Nadie más tiene que cambiarlos. Por eso son campos internos en dotnet. MQ ha creado métodos públicos para modificar estos campos, y al menos les habrían dado un nombre específico... pero no, sólo los nombres habituales:

void              Next(CLinkedListNode<T>*value)     { m_next=value; }
 

Hola a todos.

¿Hay alguna otra forma de eliminar elementos en CHashMap que no sea copiarlos mediante CopyTo y eliminarlos manualmente?

 

Aquí hay un par de cosas más para hundir el horno de la pobre implementación de la biblioteca. Su clase CKeyValuePair hereda la interfaz IComparable (y por lo tanto IEqualityComparable también) por alguna razón, requiriendo que el tipo de usuario Key deba soportar estas interfaces también. Aunque no hay necesidad en ello si definimos nuestro propio Comparer. En el original KeyValuePair no tiene ninguna interfaz, por supuesto.

Si sigues hurgando, encontrarás cosas aún más extrañas:

template<typename TKey,typename TVal>
CHashMap::CHashMap(IEqualityComparer<TKey>*comparer): m_count(0),
                                                      m_free_list(0),
                                                      m_free_count(0),
                                                      m_capacity(0)
  {
//--- check equality comaprer
   if(CheckPointer(comparer)==POINTER_INVALID)
     {
      //--- use default equality comaprer    
      m_comparer=new CDefaultEqualityComparer<TKey>();
      m_delete_comparer=true;
     }
   else
     {
      //--- use specified equality comaprer
      m_comparer=comparer;
      m_delete_comparer=false;
     }
  }

Es decir, si pasas accidentalmente un puntero roto al constructor, el programa no sólo seguirá funcionando tranquilamente, sino que su lógica también cambiará.

El constructor debería tener este aspecto:

template<typename TKey,typename TVal>
CHashMap::CHashMap(IEqualityComparer<TKey>*comparer): m_count(0),
                                                      m_free_list(0),
                                                      m_free_count(0),
                                                      m_capacity(0),
                                                      m_comparer(comparer),
                                                      m_delete_comparer(false)
{ }

Y noPOINTER_INVALID . Y hay una firma de constructor diferente para el comparador por defecto.

 
¿Hay algún ejemplo de cómo aplicar correctamente una plantilla CQueue<T> con una clase arbitraria como parámetro T?
 
Ya ha sido en un hilo paralelo. Pedir la prohibición.
 

¿Puedes decirme por qué el código no compila?

#include <Generic\HashMap.mqh>
void OnStart()
  {
   CHashMap<ENUM_CHART_PROPERTY_INTEGER,int> mapI;    // эта срока компилируется без ошибок
   CHashMap<ENUM_CHART_PROPERTY_DOUBLE,double> mapD;  // здесь ошибки компиляции: 'NULL' - cannot convert enum  HashMap.mqh     21      39. 'NULL' - cannot convert enum        HashMap.mqh     462     30
   CHashMap<ENUM_CHART_PROPERTY_STRING,string> mapS;  // здесь ошибки компиляции: 'NULL' - cannot convert enum  HashMap.mqh     21      39. 'NULL' - cannot convert enum        HashMap.mqh     462     30

  }

El problema está en los enums del sistema: ENUM_CHART_PROPERTY_DOUBLE, ENUM_CHART_PROPERTY_STRING algo está mal en ellos. Si utilizo mi propio enum como tipo de clave, la compilación también funciona.