In my opinion,the using of a function-like macro in C++ is similar to the using of a common function. It seems to be like this:
macroFunctionName(arg1, arg2, arg3);
However, the using of Q_PROPERTY usually looks like this:
Q_PROPERTY(Qt::WindowModality windowModality READ windowModality WRITE setWindowModality)
As we can see, they are different.There is no comma in the using of Q_PROPERTY.I have never seen a function-like macro which was used like Q_PROPERTY.I am even not sure whether Q_PROPERTY is a function-like macro in C++.So is it ill-formed in C++? Or it's just a special syntax for MOC in Qt?
I tried to find it in the C++ standard document but nothing about it was found.
I looked in Qt's ./src/corelib/kernel/qobjectdefs.h file for the definition, and it looks like this:
#define Q_PROPERTY(...) QT_ANNOTATE_CLASS(qt_property, __VA_ARGS__)
... which would make Q_PROPERTY a variadic macro. Of course all it does is expand out to QT_ANNOTATE_CLASS, which is a different macro, one that Qt's moc utility presumably knows how to handle in a meaningful way when generating its moc_*.cpp files.
As for the use of spaces rather than commas; you're right, the preprocessor doesn't treat spaces as argument-separators. I suspect that the C++ preprocessor is simply passing the entire line (i.e. "Qt::WindowModality windowModality READ windowModality WRITE setWindowModality") into the QT_ANNOTATE_CLASS macro as a single argument, and that moc's QT_ANNOTATE_CLASS macro-definition is doing some stringification preprocessor tricks in order to parse it as a string-argument.
Related
I have a function in a header file:
template <int line>
inline void log() {}
And then I try this trick to make using it easier:
#define LOG_LINE log<__LINE__>()
And then in a .cpp file I do:
void main()
{
LOG_LINE;
}
And it seems that it works the way I'd like it to. I get the line from .cpp file, not the line at which LOG_LINE is declared in .h file. But I don't understand how it works. Does C++ perfrom double-pass preprocessing, leaving special macros like __LINE__ for second pass? Is this portable (standard) behavior? Should I expect this to work with all major C++ compilers? So far I've only tried MSVC.
One should distinguish between the number of passes through the entire input, which is what terms like single-pass normally refer to, and handling of nested expansions. The preprocessor normally expands all macros in a single pass through the file, but it correctly expands the expanded forms, until there is nothing left to expand.
That is, LOG_LINE gets expanded to log<__LINE__>(), where __LINE__ again gets expanded to 3, producing the final expansion log<3>() — all in a single pass through the compilation unit.
Yes, this is portable, standard behaviour. Yes you can depend on it.
The reason is that the #define command simply stores the tokens that constitute the expansion text without interpreting it or expanding it at all. Because they are tokens, white space and comments are not stored.
Then when the macro name is used in the program text, it is replaced by the expansion text (and any arguments as needed). Then any tokens in the substituted text are scanned and replaced, and so on (except there is no recursive replacement).
In your case it takes two expansions to get to the underlying line number.
See N3797 16.3. It's relatively readable, for a standards document. There are examples quite close to what you're asking.
This does not need double pass preprocessing. This is about the order of expansion of nested macros (well, in a sense, an expression is expanded in as many passes as needed to expand all the nested macros). A quote from an answer to this question:
All arguments which don't appear after the # operator or either side of a ## are fully macro expanded when they are replaced, not before the function-like macro is expanded.
I'm programming a c++ application on an stm32f4 chip which has several IOs to control. One of my colleagues suggested to make preprocessor statements to all of these IOs to make the code more readable.
For example:
#define FAN_ON GPIO_SetBits(GPIOD, GPIO_Pin_0);
#define FAN_OFF GPIO_ResetBits(GPIOD, GPIO_Pin_0);
Is this ok this way, and if not, why?
I have not that much microcontroller experience yet, but I read that semicolons shouldn't be used in preprocessor statements and I'm also not sure if it is a good style to use functions in precompiler statements?
Thank you for your help!
It's fine in theory, but you're right in that the semicolons should be avoided.
It's best to wrap the code in a dummy loop:
#define FAN_ON do { GPIO_SetBits(GPIOD, GPIO_Pin_0); } while(false)
This makes the macro behave like a single statement.
To answer your first question, even though this is common, it is pretty bad style to use preprocessor statements to define functions, except when you really need the preprocessor. You really need the preprocessor when you need things like __LINE__, or preprocessor substitutions tricks like put the function name in a char * variable. You could define a function void fan_on(void) and void fan_off(void) instead of those macros, you can even declare them static inline if you want to declare them in a header like you would do with macros. Functions can be better used by the debugger than macros, and better debugged.
As you said if you still want to use macros you should not use semicolons, and use a do while(0) structure, if you don't using the macro if a single-line if block will only execute the first line of the macro.
Just caught a silly bug. I have a zip processing library with a CreateFile() function in it. Winbase.h, included somewhere deep in my headers, redefines it as CreateFileW and linker goes nuts.
Of course I will exclude winbase in this particular case. It just shouldn't be in the scope in the first place. But the theoretical question is still interesting,
Is there a way to suppress some defines locally?
You can get around the macro by putting parentheses around the name:
(CreateFile)(arguments);
This works because the macro CreateFile is a function-like macro (i.e. it takes a list of arguments in parentheses); the right parenthesis after the name doesn't match the syntax for using a function-like macro, so the preprocessor does not expand it.
Of course, the "right" solution is to name the function properly, i.e., create_file. <g>
Removing the offending header file is ALWAYS the best solution for this (especially one as large as windows.h or winbase.h - they are included far too freely for my taste in many projects).
The only other solution is #undef offending_symbol.
Of course, another important thing is "do not use names that match the Windows/Linux system call names" - but CreateFile is a very obvious name for a function that creates a file, so I can see the temptation.
Preprocessor macros have no notion of C++ scope. #defines are just text replacements. If you want to have a 'local' #define, you do something like this:
#define CreateFileW CreateFile
... // here I can use the macro
#undef CreateFileW
Or in your case
#undef CreateFileW
... // Here the macro is not available
#define CreateFileW CreateFile
There is
#undef
which removes defines (but nothing else).
Apart from the aforementioned #undef there technically is not much you can do against #defines, at least not portably.
The best way is to not use #define at all, or at least as little as possible and as constrained as possible. Sometimes you just need a macro to generate some boilerplate code a few times. Be sure to #undef that macro once you are done. The only other valid applications of #define I can think of are include guards and flags for conditional preprocessing.
For #define-deseases like the WinAPI headers you just should constrain them as much as possible. Don't use the #defined types of that API in your headers. You almost never want to use an API all over your application, so use it only in the cpps of a small layer around the API. Reducing the dependencies that way gives a lot more than just disinfecting the rest of your code.
I want to simplify things, by not creating a list of enum separately, but create the enums along the function call which creates the data where i point with those enums.
I tried to make #define which would create another #define, but it didnt work:
int defcounter = 0;
#define make_def(enumname, somedata) \
#define enumname defcounter \
defcounter++; \
func_call(somedata); \
void createstuff(){
make_def(MY_ENUM_NAME, mydata);
make_def(MY_OTHER_ENUMNAME, mydata);
}
void dostuff(){
somefunc_call(MY_ENUM_NAME);
somefunc_call(MY_OTHER_ENUMNAME);
}
But this will create error at the #define enumname:
error C2162: expected macro formal parameter
How can I make this work?
It is impossible to create new types (classes, enums, unions, whatever) at runtime in C++. One of the major features of C++ is that it is statically typed - all types must be known at compile time.
Preprocessor commands (#define, #if, #pragma, #include, ...) cannot appear in macros / defines. The problem is, that the CPP (C-Preprocessor) seperates commands by newlines, while C and C++ are unaware of newlines. In C/C++ you can write everything on one line, for preprocessor commands, you can't.
#define MY_MACRO(name) \
#define name##_macro something_cool \
enum name{ \
.... \
}
// somewhere else
void myfunc(){
MY_MACRO(myfunc_enum);
}
Now, at preprocessing time, those lines all get glued into one big line, thanks to the \ backslash:
#define MY_MACRO(name) #define name##_macro something_cool enum name{....}
Now, how would that macro look at usage?
void myfunc(){
#define name##_macro something_cool enum name{....};
}
Now, the preprocessor has to run over that #define again. But exactly what belongs to the #define, and what doesn't? For the coder it was clear when the macro was written in seperate lines, but now it isn't anymore.
What exactly is your desired output? You need to explain what you think you might get as output from the C preprocessor.
You have scope problems and an attempt to define a macro inside the replacement text of another macro.
Scope
The macro make_def() invokes an undefined function 'func_call'. The createstuff() function uses an undefined variable mydata. And function dostuff() seems to call an undefined function somefunc_call() with an enum that might, perhaps, have been defined inside a separate function.
If an enumeration is defined inside one function, that enumeration is not available to code outside that function, and specifically is not available to either called functions or calling functions. That alone limits the utility of what you seem to be attempting to do. (Yes, the enumeration values might be implicitly converted to int or some similar type, but it is not really the enumeration type that is being used.)
Defining macros in macros
You cannot create a macro that itself contains #define or any other preprocessor directive in its replacement text.
If the outer macro is invoked, the expansion does not interpret the inner #define as being a preprocessor directive, so it almost always ends up as an error, In context the # must be a stringize operator, and the word 'define' after it would have to be the name of an argument to the outer macro to have a chance of working.
// Does not work as intended
#define macro(define, prefix) #define another(name) foo(prefix ## name)
macro(something, other);
Generates:
"something" another(name) foo(othername);
The _Pragma in C99 is a partial exception to the 'a macro expansion cannot contain a preprocessor directive', but it (_Pragma) does not start with #.
Your macro is incorrect, since you cannot use a macro to create another macro, unfortunately, as the toke # has special meaning in the expansion-list: it can either quote a macro argument, or expand another macro. One easy (albeit poorly designed) way you could do this is just to use old c-style #define MY_ENUM_NAME valueas c macro do not respect scope, but this would not be good design. Another possibility is to pass in string arguments and hash on them, but all depends on what you want to do.
I am interested in defining my own language inside a C++ block (lets say for example main) and for that purpose I need to use the preprocessor and its directives my problem relies to the below rule:
#define INSERT create() ...
Is called a function-like definition and preprocessor does not allow any whitespaces in what we define ,
So when I use a function of my own language I got to parse right handy the below statement:
INSERT INTO variable_name VALUES(arg_list)
to a different two function calls lets say
insertINTO(variable_name) and valuePARSE(arg_list)
but since the preprocessor directive rules do not allow me to have whitespaces in my definition how I can reach the variable_name and then make the call to the first function call I want to achieve?
Any clues would be helpful.
PS: I tried using g++ -E file.cpp to see how preprocessor works and to adjust the syntax to be valid c++ rules.
The preprocessor included with most C++ compilers is probably way too weak for this kind of task. It was never designed for this kind of abuse. The boost preprocessor library could help you on the way, but I still think you're heading down a one-way street here.
If you really want to define your language this way, I suggest you either write your own preprocessor, or use one that is more powerful than the default one. Here is one chap who tried using Python as a C++ preprocessor.
1) define INSERT create() is not a function-like macro it's object-like, something like define INSERT(a, b, c) create(a, b, c) would be;
2) if you want to expand INSERT INTO variable_name VALUES(arg_list) into insertINTO(variable_name); valuePARSE(arg_list); you can do something like:
#define INSERT insertINTO(
#define INTO
#define VALUES(...) ); valueParse(__VA_ARGS__);
3) as you can see macros get ugly pretty easy and even the slightest error in your syntax will have you spend a lot of time tracking it down
4) since it's tagged C++ take a look at Boost.Proto or Boost.Preprocessor.