How do I go through an enumeration consistently? - page 7

 
Комбинатор:

What about the normal names that are in the comments?

Dynamic ENUM is for internal use, it's not shown in the settings window. Normal names/comments are not really needed
 

By the way, there seems to be an error in the mql preprocessor.

#define  i ##nt  ll;

expands to 'i nt ll;' and gives an error:

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


Regarding the comments in the enumeration - supposedly they should be twitching up to the C preprocessor. So even if it was possible to cram a comment in, it would be unlikely to have an effect. In a good way, you should change the syntax (to _cmnt_, for example) and change the call sequence of the C preprocessor with the preprocessor that pulls the comments. Prospects for such reforms are unlikely, I think ))

 
pavlick_:

By the way, there seems to be an error in the mql preprocessor.

expands to 'i nt ll;' and gives an error:

You have an error somewhere. It expands correctly: 'nt ll;
 
Alexander Puzanov:
Dynamic ENUM is for internal use, the settings window doesn't show these. Normal names/comments are not really needed
Such a dynamic enum can be shoved into a much nicer form.
 

The last method required to write the blanks manually for enum and the function that returns an array of values. I decided to figure it out and write it in such a way that it is no longer needed. However, it cannot be compiled in mql, there are no macros with variable number of arguments, but theoretically they can appear. Anyway, here's what I've got:

// Выглядит страшно, да )). Но это универсальная заготовка
// Можно засунуть в какой-нибудь 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

// Generated code for 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);
// }

Article on this subject http://jhnet.co.uk/articles/cpp_magic. All in all, a lot of magic, of course. But the technique can be useful for a wide range of tasks referring to preprocessor code generation.

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...
 
Bummer) but kudos to you.
 

I read the thread with interest, all very cool with macros.

It's just not clear, why do we need all this dancing with enum? Can you give a practical example?

It's clear about TF, but what else?

 
pavlick_:

However it cannot be compiled in mql, there are no macros with variable number of arguments, but theoretically they can appear.

In MQL5 macros not only have a fixed number of arguments, but their number is limited to 8. So you can make an enum for only 3 values.

As for theoretical appearance, it will probably be faster to get an in-house function for enum parsing, as the developers have already promised to do something.

 
Alexey Navoykov:

In MQL5 macros not only have a fixed number of arguments, but the number of arguments is limited to 8. So we can make an enum for only 3 values.

As for the theoretical appearance, it's probably faster to get an in-house function for enum parsing. The developers have already promised to come up with something.

No iterator to enumerate enum values is planned.
Use previously proposed method of enumeration using array.
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:
No iterator is planned for enumerator value enumeration.
Use the previously suggested method of enumerating values using an array.
It turns out to be the same switch, but from the side. That is, two lists will need to be maintained in any case: the enumerator itself and the array (switch cases).
Reason: