Macros dont allow empty arguments anymore - why?

 
#define func(arg1, arg2) Print(arg1); arg2;

func("Hello", ExpertRemove()) // fine
func("Hello",) // Warning


Makes no sense for me. There are many cases, when I explicitly do not want to have the second argument, but I also dont wanna mess up my code with even more macros with different names. On top, this works, but is actually the same:


#define func(arg1, arg2) Print(arg1); arg2;
#define _ 

func("Hello", ExpertRemove()) // fine
func("Hello", _) // fine

 

Why "anymore"?

AFAIK, MQL5 never supported variadic macros.

Why not to use functions?
 

Its since the last update. Before there was never a warning. 

Why not functions? Cuz they don't work for every case.
Example: I use this macro to define class members. One line, defines function name, datatype, varname, the code to be executed when set, code to be executed when get. It keeps my code (in my opinion) easier to understand at a glance. 

Same without macro:


The macro is:

// Property w/ member var (read/write)
#define IMPLEMENT_MEMBER_SET_GET(function_name,datatype,member_var,command_onset,command_onget) protected: datatype member_var; public: void function_name(datatype value) { if (member_var==value) return; member_var=value; { command_onset; } } public: datatype function_name(void) { { command_onget; } return member_var; } 
#define _set(code) {code;}
#define _get(code) {code;}
#define _


I also have macros for ForEach functionality, and many other stuff. 

 

Ok, so the question is not about skipping optional argument as a whole (which is not supported unfortunately), but about newly emerged warning about empty space after the coma.

Well, I think the warning is useful. Your workround with empty _ definition is much better than the hanging coma, imho, because it's clearly declares your intention, whereas the omission can be (and looks like) accidental.

PS. One little note about macros. Despite the fact that macros are indespensible with codegeneration (as in your case), it's very hard to debug such codes. Which is why I prefer to refactor such codes (whenever possible) into classes/templates. For example, you could have a template of SmartValue(T) with getter/setter and even optional event callback for intercepting/broadcasting changes, if it will be needed in future.

 
Stanislav Korotky #:

Ok, so the question is not about skipping optional argument as a whole (which is not supported unfortunately), but about newly emerged warning about empty space after the coma.

Well, I think the warning is useful. Your workround with empty _ definition is much better than the hanging coma, imho, because it's clearly declares your intention, whereas the omission can be (and looks like) accidental.

PS. One little note about macros. Despite the fact that macros are indespensible with codegeneration (as in your case), it's very hard to debug such codes. Which is why I prefer to refactor such codes (whenever possible) into classes/templates. For example, you could have a template of SmartValue(T) with getter/setter and even optional event callback for intercepting/broadcasting changes, if it will be needed in future.

Yeah you are right. Actually I like the '_' definition, since its very close to _ in C# which means "suppress/empty". As long as it stays like that, I am fine with it. I am only concerned, that this also could become a problem in the future. 

Regarding debugging - you are also right. Of course I wouldn't use for more complex code, but stuff like such, there is actually nothing to debug. Nonetheless, its all a matter or personal taste. 

 
Doerk Hilger #:

Yeah you are right. Actually I like the '_' definition, since its very close to _ in C# which means "suppress/empty". As long as it stays like that, I am fine with it. I am only concerned, that this also could become a problem in the future. 

Regarding debugging - you are also right. Of course I wouldn't use for more complex code, but stuff like such, there is actually nothing to debug. Nonetheless, its all a matter or personal taste. 

I also noticed this changed behavior. I could live with an underscore or EMPTY_ARG #defined to be empty, but what makes me think that this is a bug or at least an unwanted behavior is that the warning is triggered only when the missing argument is the last one of the macro. For example, consider this code:

#define MACRO(A, B, C) \
  A B void C(void) { Print("Hello!"); }

MACRO(inline, , function)

void OnStart()
{
  function();
}

This code compiles without any warning, instead the following code will generate the warning:

#define MACRO(A, B, C) \
  A C void B(void) { Print("Hello!"); }

MACRO(inline, function, )

void OnStart()
{
  function();
}
 
Doerk Hilger:


Makes no sense for me. There are many cases, when I explicitly do not want to have the second argument, but I also dont wanna mess up my code with even more macros with different names. On top, this works, but is actually the same:


Fixed in build 5692.
 
Alain Verleyen #:
Fixed in build 5692.
I get why you don’t want to create extra macros with different names. If you sometimes need to call a macro with one argument and sometimes with two, you can use argument overloading with  __VA_OPT__  (in C++20) or a macro that counts the number of arguments. That way you keep a single macro name but change its behavior depending on whether the second argument is present. If you show your current approach, I can suggest how to generalize it without duplicating code.
 
Peter Hudson #:
I get why you don’t want to create extra macros with different names. If you sometimes need to call a macro with one argument and sometimes with two, you can use argument overloading with  __VA_OPT__  (in C++20) or a macro that counts the number of arguments. That way you keep a single macro name but change its behavior depending on whether the second argument is present. If you show your current approach, I can suggest how to generalize it without duplicating code.
Irrelevant. MQL is not C++.