Como é que passo por uma enumeração de forma consistente? - página 7

 
Комбинатор:

E os nomes normais que estão nos comentários?

Dynamic ENUM é para uso interno, não é mostrado na janela de ajustes. Os nomes / comentários normais não são realmente necessários
 

A propósito, parece haver um erro no pré-processador de mql.

#define  i ##nt  ll;

expande-se para 'i nt ll;' e dá um erro:

'i nt' - undeclared identifier    t_t_t.mq4    50    1


Quanto aos comentários na enumeração - supostamente deveriam estar a contrair-se até ao pré-processador C. Por isso, mesmo que fosse possível introduzir um comentário, seria pouco provável que isso tivesse efeito. De uma boa maneira, deve alterar a sintaxe (para _cmnt_, por exemplo) e alterar a sequência de chamada do pré-processador C com o pré-processador que puxa os comentários. As perspectivas de tais reformas são improváveis, penso eu ))

 
pavlick_:

A propósito, parece haver um erro no pré-processador de mql.

expande-se para 'i nt ll;' e dá um erro:

Tem um erro algures. Expande-se correctamente: 'nt ll;
 
Alexander Puzanov:
Dynamic ENUM é para uso interno, a janela de ajustes não os mostra. Os nomes/comentários normais não são realmente necessários
Uma enumeração tão dinâmica pode ser empurrada para uma forma muito mais agradável.
 

O último método necessário para escrever manualmente os espaços em branco para a enumeração e a função que devolve um conjunto de valores. Decidi descobri-lo e escrevê-lo de tal forma que já não seja necessário. Contudo, não pode ser compilado em mql, não existem macros com número variável de argumentos, mas teoricamente podem aparecer. Seja como for, eis o que tenho aqui:

// Выглядит страшно, да )). Но это универсальная заготовка
// Можно засунуть в какой-нибудь cpp_magic.h
//cpp_magic.h
#define  EVAL(...) EVAL1024(__VA_ARGS__)
#define  EVAL1024(...) EVAL512(EVAL512(__VA_ARGS__))
#define  EVAL512(...) EVAL256(EVAL256(__VA_ARGS__))
#define  EVAL256(...) EVAL128(EVAL128(__VA_ARGS__))
#define  EVAL128(...) EVAL64(EVAL64(__VA_ARGS__))
#define  EVAL64(...) EVAL32(EVAL32(__VA_ARGS__))
#define  EVAL32(...) EVAL16(EVAL16(__VA_ARGS__))
#define  EVAL16(...) EVAL8(EVAL8(__VA_ARGS__))
#define  EVAL8(...) EVAL4(EVAL4(__VA_ARGS__))
#define  EVAL4(...) EVAL2(EVAL2(__VA_ARGS__))
#define  EVAL2(...) EVAL1(EVAL1(__VA_ARGS__))
#define  EVAL1(...) __VA_ARGS__
#define  SECOND(a, b, ...) b
#define  FIRST(a, ...) a
#define  CAT(a,b) a ##  b
#define EMPTY()
#define  DEFER1(m) m EMPTY()
#define  DEFER2(m) m EMPTY EMPTY()()
#define  DEFER3(m) m EMPTY EMPTY EMPTY()()()
#define  DEFER4(m) m EMPTY EMPTY EMPTY EMPTY()()()()
#define  IS_PROBE(...) SECOND(__VA_ARGS__, 0)
#define  PROBE() ~, 1
#define  NOT(x) IS_PROBE(CAT(_NOT_, x))
#define _NOT_0 PROBE()
#define  BOOL(x) NOT(NOT(x))
#define  HAS_ARGS(...) BOOL(FIRST(_END_OF_ARGUMENTS_ __VA_ARGS__)())
#define _END_OF_ARGUMENTS_() 0
#define  IF_ELSE(condition) _IF_ELSE(BOOL(condition))
#define _IF_ELSE(condition) CAT(_IF_, condition)
#define _IF_1(...) __VA_ARGS__ _IF_1_ELSE
#define _IF_0(...)             _IF_0_ELSE
#define _IF_1_ELSE(...)
#define _IF_0_ELSE(...) __VA_ARGS__
#define  MAP1(m, first, ...)          \
  m(first)                           \
  IF_ELSE(HAS_ARGS(__VA_ARGS__))(    \
  DEFER2(_MAP1)()(m, __VA_ARGS__)    \
  )()
#define _MAP1() MAP1
#define  MAP2(m, first, second, ...)  \
  m(first, second)                   \
  IF_ELSE(HAS_ARGS(__VA_ARGS__))(    \
  DEFER2(_MAP2)()(m, __VA_ARGS__)    \
  )()
#define _MAP2() MAP2
// main.cpp
#include <stdio.h>
#include "cpp_magic.h"

#define  CREATE_ENUM_HELPER_1(el, val)  el = val,
#define  CREATE_ENUM_HELPER_2(el, val)  el,
#define  CREATE_ENUM(name, ...)                                     \
  enum name{                                                       \
    EVAL( MAP2(CREATE_ENUM_HELPER_1, __VA_ARGS__) )                \
  };                                                               \
  unsigned get_##name##_array(int *ar){                            \
    int temp[] = {                                                 \
    EVAL( MAP2(CREATE_ENUM_HELPER_2, __VA_ARGS__) )                \
    };                                                             \
    if(ar != NULL)                                                 \
      for(unsigned i = 0;  i < sizeof(temp) / sizeof(int);  ++i){  \
        ar[i] = temp[i];                                           \
    }                                                              \
    return sizeof(temp) / sizeof(int);                             \
  };

CREATE_ENUM(enum1, q,1, e,3, t,65, z,90)
CREATE_ENUM(enum2, ww,100, ss,-3, dh,21)
struct S{
  CREATE_ENUM(enum3, q,871, e,213, t,226)
}s;

int main()
{
  int ar[100];

  printf("----enum1-----\n");
  get_enum1_array(ar);
  for(unsigned i = 0;  i < get_enum1_array(NULL);  ++ i)
    printf("%d\n", ar[i]);

  printf("----enum2-----\n");
  get_enum2_array(ar);
  for(unsigned i = 0;  i < get_enum2_array(NULL);  ++ i)
    printf("%d\n", ar[i]);

  printf("----enum3-----\n");
  s.get_enum3_array(ar);
  for(unsigned i = 0;  i < s.get_enum3_array(NULL);  ++ i)
    printf("%d\n", ar[i]);
}

Выхлоп printf:
 ----enum1-----
 1
 3
 65
 90
 ----enum2-----
 100
 -3
 21
 ----enum3-----
 871
 213

226

// Código gerado para emum1
// enum enum1{
// q = 1,
// e = 3,
// t = 65,
// z = 90,
// };
// unsigned get_enum1_array(int *ar){
// int temp[] = { q, e, t, z, };
// if(ar != NULL)
// for(unsigned i = 0; i < sizeof(temp) / sizeof(int); ++i){
// ar[i] = temp[i]; }
// return sizeof(temp) / sizeof(int);
// }

Artigo sobre este assunto http://jhnet.co.uk/articles/cpp_magic. Em suma, muita magia, claro. Mas a técnica pode ser útil para uma vasta gama de tarefas referentes à geração de códigos de pré-processador.

C Pre-Processor Magic - Articles - Jhnet
  • jhnet.co.uk
The C Pre-Processor (CPP) is the somewhat basic macro system used by the C programming language to implement features such as and which allow very simple text-substitutions to be carried out at compile time. In this article we abuse the humble to implement if-statements and iteration. Before we begin, a disclaimer: these tricks, while perfectly...
 
Vagabundo) mas kudos para si.
 

Li o fio com interesse, tudo muito fixe com macros.

Não está claro, porque é que precisamos de toda esta dança com enumeração? Posso dar-vos um exemplo prático?

É claro sobre a TF, mas que mais?

 
pavlick_:

Contudo, não pode ser compilado em mql, não existem macros com número variável de argumentos, mas teoricamente podem aparecer.

Nas macros MQL5 não só há um número fixo de argumentos, como também o seu número está limitado a 8, pelo que se pode fazer um enumero para apenas 3 valores.

Quanto à aparência teórica, será provavelmente mais rápido obter uma função interna para enumerar a análise, uma vez que os criadores já prometeram fazer algo.

 
Alexey Navoykov:

Nas macros MQL5 não só temos um número fixo de argumentos, como o número de argumentos é limitado a 8. Por isso, podemos fazer um enumero para apenas 3 valores.

Quanto à aparência teórica, é provavelmente mais rápido obter uma função interna para a análise de enumeração. Os programadores já prometeram que iriam pensar em algo.

Não está previsto nenhum iterador para enumerar valores de enumeração.
Utilizar o método de enumeração anteriormente proposto, utilizando matriz.
enum Enum
 {
  VAL_0,
  VAL_1,
  ...
 };

const  Enum EnumValues[]={ VAL_0, VAL_1, ... };

for(uint i=0;i<ArraySize(EnumValues);i++)
   Print(EnumToString(EnumValues[i]));
 
Ilyas:
Não está previsto nenhum iterador para enumeração de valores de enumeração.
Utilizar o método anteriormente sugerido de enumeração de valores utilizando uma matriz.
Acontece que é o mesmo interruptor, mas pelo lado. Ou seja, duas listas terão de ser mantidas em qualquer caso: o próprio enumerador e a matriz (casos de troca).
Razão: