Особенности языка mql5, тонкости и приёмы работы - страница 306

 
Andrei Iakovlev #:
Как сделать так, чтобы и при вызове функции в коде тоже происходило очищение?

Если окно экспертов пустое, кнопка Очистить не нажимается.

Может возможно добавить проверку того, нажимается она или нет, и если нажимается, очищать, пока не станет ненажимаемой?

 
#define TOSTRING(A) TOSTRING2(A)
#define TOSTRING2(A) #A

int Num1 = 123;
int Num2 = 456;
int Num3 = 789;

#define MACROS1 Num1
#define MACROS2 Num2, Num3

void f( int i, int j = 0 ) { Print((string)i + "," + (string)j); }

void OnStart()
{
  f(MACROS1); // 123,0
  f(MACROS2); // 456,789
  
  Print(TOSTRING(MACROS1)); // Num1
  Print(TOSTRING(MACROS2)); // Num2: too many arguments for function-like macro 'TOSTRING2'
}

Возможно ли в этом месте вывести полностью MACROS2: Num2,Num3?

 
fxsaber #:

Можно ли в этот момент вывести полностью MACROS2: Num2,Num3?


#define   TOSTRING(A) TOSTRING2(A)
#define   TOSTRING2(A) #A

#define   TOSTRING_2P(AB) TOSTRING_2P2(AB)
#define   TOSTRING_2P2(A,B) TOSTRING2(A) ", " TOSTRING2(B)

int Num1 = 123;
int Num2 = 456;
int Num3 = 789;

#define   MACROS1  Num1
#define   MACROS2  Num2, Num3
#define   SPLIT(x) Num2, Num3

void f( int i, int j = 0 ) { Print((string)i + "," + (string)j); }

void OnStart()
{
  f(MACROS1); // 123,0
  f(MACROS2); // 456,789

  Print(TOSTRING(MACROS1));    // Num1
  Print(TOSTRING_2P(MACROS2)); // Num2, Num3
}

Для разделения, объединения и структурирования параметров вложенных макросов требуется еще один (непрямой) макрос второго уровня.
 
amrali #:


Для разделения, объединения и структурирования параметров вложенных макросов требуется еще один (непрямой) макрос второго уровня.

Вы предлагаете для каждого случая создавать свою версию макроса перевода в строку. Но тогда решение не универсальное, т.к. зависит от вида макроса.

Получается, что нет общего механизма перевода макроса в строку.

 
fxsaber #:

Вы предлагаете создать отдельную версию макроса перевода строки для каждого случая. Но тогда решение не будет универсальным, потому что оно зависит от типа макроса.

Получается, что общего механизма перевода макроса в строку не существует.

Следите за вложенными вызовами макросов. Параметры макросов, которые сами являются макросами, расширяются на 2 этапа;

void func(int arg) {  }   

func(MACROS1); 

если arg - макрос, то он будет полностью расширен (т. е. оценен, или произойдет текстовая замена) во время компилятора/парсера.

#define  MACROS1 (......) 

#define TOSTRING(arg) (......) 

TOSTRING(MACROS1));

Если arg - макрос (т. е. вложенные вызовы макросов), то при первом проходе он не будет расширен (не произойдет текстовой замены внутри тела макроса).

Также при первом проходе оператор # stringify и оператор ## concat становятся ON HOLD. Таким образом, вам нужен макрос второго уровня перенаправления.

При втором проходе тело макроса снова оценивается для дальнейших расширений (текстовая замена, stringify и concat).

Это ограничение макросов, поскольку они оцениваются компилятором во время выполнения как текст (а не как исполняемый код).

 
amrali #:

Это ограничение макросов, поскольку они оцениваются компилятором во время выполнения как текст (а не как исполняемый код).

Решение.

#define TOSTRING(A) TOSTRING2((A))
#define TOSTRING2(A) StringSubstr(#A, 1, StringLen(#A) - 2)

int Num1 = 123;
int Num2 = 456;
int Num3 = 789;

#define MACROS1 Num1
#define MACROS2 Num2, Num3

void f( int i, int j = 0 ) { Print((string)i + "," + (string)j); }

template <typename T>
void f2( T ) {}

void OnStart()
{
  f(MACROS1); // 123,0
  f(MACROS2); // 456,789
  
  Print(TOSTRING(MACROS1)); // Num1
  Print(TOSTRING(MACROS2)); // Num1, Num2
}
 

Если речь зашла о параметрических макросах, вот интересный вопрос: как развернуть в макросе комментарий. В таком макросе

#define INPUT_PAR(TYPE, NAME, VAL, MIN, STEP, HI, MAX)  	\
        const TYPE #NAME##_MIN  = (MIN);			\
        const TYPE #NAME##_HI   = (HI);				\
        const TYPE #NAME##_MAX  = (MAX);			\
        input TYPE NAME = (VAL); // #NAME [#MIN/#STEP/#HI]

комментарий нужен, чтобы заменить текст в input в терминале. Однако макрос не разворачивает комментарий, а опускает его.

 
Edgar Akhmadeev #:

как развернуть в макросе комментарий.

Никак.
 
fxsaber #:
Никак.

Верю. Спасибо.

 
fxsaber # :

Solution.

I don't consider it a solution using pure macros. Using a helper function like StringSubst() or Print() that is evaluated at runtime can help to escape the default order of macro parameter expansion (2 steps). These are the semantics of how the C compiler works. 

Stringifying the args can be helpful for displaying debug messages. But in order to keep the meaning of args (work on them), you have to use other indirection macros.

FYI, comments are removed by the parser from the source code file before any macro is expanded, so comments inside macros are deleted.