Biblioteca de classes genéricas - bugs, descrição, perguntas, recursos de uso e sugestões - página 29

 
Alexey Volchanskiy:

A MSDN chama-lhe um buffer de anéis, eu não inventei o nome.

link para o

Alexey Navoykov:

...e terminando com uma conversão para argumentos por referência, e não apenas por valor.

pode haver um problema com os literais

 
TheXpert:

ligação no estúdio.

Pode haver um problema com os literais

Preguiçoso para procurar novamente esse artigo, mas estiquei-o um pouco. Uma lista com um ou dois anéis é baseada numa lista ligada, mas o último elemento armazena uma ligação à primeira.

 
TheXpert:

pode haver problemas com os literais

Não, eu tenho a classe "valores" herdada da classe "referência" de base, puramente como um invólucro. Portanto, basta seleccionar a versão desejada da classe e ir
 
Alexey Volchanskiy:

Uma lista ligada simples ou dupla é baseada numa lista ligada, mas o último item da lista ligada armazena uma ligação ao primeiro item.

A questão é essa: é um "base", não um substituto. Ninguém impediu os programadores de o fazer também aqui um contentor adicional. Em vez de substituir conceitos comuns
 
Alexey Navoykov:

O mais provável é que quem quer que tenha portado estas aulas tenha decidido simplificar a sua vida simplificando o código. Em vez de dois ponteiros m_first e m_last ele fez um ponteiro m_head...

Olhou para as fontes dotnet, e percebeu a razão. A própria classe LinkedList é portada correctamente, há realmente apenas uma cabeça ponteiro, que é tanto o início como o fim. Assim, a implementação interna é de facto em loop, mas o comportamento externo não. MQ tem um erro na classe CLinkedNode (Próximo e Métodos anteriores). Eis como é a sua implementação 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; }
        }

E aqui está como é portado para MQL:

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

Talvez estivessem desatentos e se tenham enganado.

Mas em geral também estou um pouco surpreendido com a implementação do dotnet. Porque não foi possível fazer dois apontamentos na própria lista (primeiro e último) em vez de uma cabeça. Isso evitaria verificações adicionais nos métodos de nodo de lista acima, ou seja, eles iriam parecer exactamente como o MQ agora, mas tudo funcionaria correctamente. Claro que abrandaria um pouco o processo de inserção/eliminação dos nós, mas aceleraria a iteração sobre eles, o que é uma prioridade muito maior. O Próximo e o Anterior são definitivamente chamados mais frequentemente, do que os nós adicionados. Foi assim que o fiz, pensei que o mesmo seria verdade para a melkomsoft. Mas não importa )

A propósito, a MQ tem outro bug na implementação do CLinkedListNode e do CRedBlackTreeNode. (excepto m_value) destinam-se a ser alterados exclusivamente pela própria classe da lista. Ninguém mais tem de os alterar. É por isso que são campos internos em dotnet. MQ criou métodos públicos para modificar estes campos, e pelo menos ter-lhes-iam dado um nome específico... mas não, apenas os nomes habituais:

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

Olá a todos!

Existe alguma outra forma de eliminar itens no CHashMap que não seja copiá-los através de CopyTo e apagá-los manualmente?

 

A sua classe CKeyValuePair herda a interface IComparable (e portanto IEqualityComparable também) por alguma razão, exigindo que a Key do tipo de utilizador suporte estas interfaces também. Embora não haja necessidade disso se definirmos o nosso próprio Comparador. No original, a KeyValuePair não tem interfaces, claro.

Se continuar a bisbilhotar, vai encontrar coisas ainda mais estranhas:

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

Ou seja, se passar um ponteiro partido para o construtor acidentalmente, o programa não só continuará a trabalhar em paz, como a sua lógica também mudará!

O construtor deve ter 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)
{ }

E nenhumPOINTER_INVÁLIDO . E há uma assinatura de construtor diferente para o comparador padrão.

 
Existe um exemplo de como aplicar correctamente um modelo CQueue<T> com uma classe arbitrária como o parâmetro T ?
 
Já esteve num fio paralelo. Pedir uma proibição.
 

Pode dizer-me porque é que o código não é compilado?

#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

  }

O problema está nos enums do sistema: ENUM_CHART_PROPERTY_DOUBLE, ENUM_CHART_PROPERTY_STRING algo está errado com eles. Se eu utilizar o meu próprio enumero como um tipo chave, a compilação também funciona.