Different syntax for #define in C/C++ including many statements - c++

I understand the syntax of #define like,
#define Pi 3.14
So it's obvious that we can use Pi constant instead of 3.14 anywhere in code to make code more readable.
But I encountered a syntax like below.
Does it mean whenever I call the macro
doIT("hello world");
the code statements within {...} will be invoked ?
Does #define allow to give such syntax.?
What does the __FUNCTION__, __VA_ARGS__ mean ?
#define doIT(str, ...) \
{ \
if (pDoLog) pDoLog->LogMsg("[%s] Error: " str, LOG_WRONG, __FUNCTION__, ##__VA_ARGS__); \
printf("[%s] Error: " str "\n", __FUNCTION__, ##__VA_ARGS__); \
}

You don't "call" a macro, and its expansion doesn't get "invoked". The preprocessor just replaces the macro with its expansion, before the code gets compiled.
A macro defined with parentheses such as doIt(str) is a "function-like macro" which means it takes arguments which can be used in the expansion of the macro.
A function-like macro with ... in the argument list indicates it can accept a variable number of arguments. The special predefined symbol __VA_ARGS__ expands to the list of arguments passed to the ... placeholder.
__FUNCTION__ is a special predefined symbol that expands to the name of the current function being compiled, so wherever the macro gets expanded it will use the name of the enclosing function.

Related

Is there a way to write a C/C++ function-like macro that tests if an object-like macro is defined and generates code uses it?

I can find other questions on the site about using #if and #ifdef inside macros, and ways to get around the restriction to achieve various things, but none of them or their answers seem to match my use-case, which seems like an obvious one to me:
// the system flags are defined as object-like macros in this header...
#include <sys/stat.h>
// naive attempt at function-like macro that of course cannot work
#define MAYBE_EXPORT_FLAG(flag) \
#if defined(flag). \
exports.Set(Napi::String::New(env, #flag), \
Napi::Number::New(env, flag)); \
#endif
Napi::Object Init(Napi::Env env, Napi::Object exports) {
MAYBE_EXPORT_FLAG(UF_NODUMP)
MAYBE_EXPORT_FLAG(UF_IMMUTABLE)
MAYBE_EXPORT_FLAG(UF_APPEND)
return exports;
}
For instance, this previous question seems similar and a workaround is provided, but I couldn't adapt that set of macros to my case, or if it is adaptable I'm not understanding something there. In any case it doesn't use the macro's parameter in the generated code.
I did find that there were some tricks around to do what some of the other questions wanted but I couldn't find a way to adapt any of them to this case. But they are quite tricky. So is there some trick or is it simply impossible?
What you end up needing to do is define a macro for every symbol of interest that expands based on whether the symbol is defined:
#include <sys/stat.h>
#ifdef UF_NODUMP
#define IFDEF_UF_NODUMP(...) __VA_ARGS__
#else
#define IFDEF_UF_NODUMP(...)
#endif
#ifdef UF_IMMUTABLE
#define IFDEF_UF_IMMUTABLE(...) __VA_ARGS__
#else
#define IFDEF_UF_IMMUTABLE(...)
#endif
#ifdef UF_APPEND
#define IFDEF_UF_APPEND(...) __VA_ARGS__
#else
#define IFDEF_UF_APPEND(...)
#endif
#define MAYBE_EXPORT_FLAG(flag) \
IFDEF_ ## flag( \
exports.Set(Napi::String::New(env, #flag), \
Napi::Number::New(env, flag)); \
)
Napi::Object Init(Napi::Env env, Napi::Object exports) {
MAYBE_EXPORT_FLAG(UF_NODUMP)
MAYBE_EXPORT_FLAG(UF_IMMUTABLE)
MAYBE_EXPORT_FLAG(UF_APPEND)
return exports;
}
This is somewhat painful and repetitive, but you can put all the repeated stuff in its own header file somewhere that you don't need to refer to much. Depending on what you are are trying to do, you might find it useful to define IFNDEF_ macros for each symbol as well.
Here's an alternate approach, for interest (with a caveat--see bolded list entry). This doesn't use your MAYBE_EXPORT_FLAG skeleton, but:
It's a bit more generic (based on pattern matching)
Usage is less verbose than giant chains of conditional directives (detects undefined flags using pattern matching)
Works with identifier-like flags (anything right-pasteable to an identifier; includes positive decimals, octals, hex numbers)
Works with parenthetical flags
WILL NOT WORK for (non-parenthetical) "negative" flags (e.g., if your system defines a flag as #define FLAG -1)
Base macros
#define SECOND(...) SECOND_I(__VA_ARGS__,,)
#define SECOND_I(A,B,...) B
#define GLUE(A,B) GLUE_I(A,B)
#define GLUE_I(A,B) A##B
#define EAT(...)
#define IF_NMATCHES_USEABLE(P_, F_, M_) M_
#define IF_NMATCHES_P(...) , IF_NMATCHES_USEABLE
#define IF_NMATCHES_CALL(P_,F_,M_) \
SECOND(IF_NMATCHES_P F_, IF_NMATCHES_D2)(P_, F_, M_)
#define IF_NMATCHES_D2(P_,F_,M_) \
SECOND(GLUE(P_, F_), IF_NMATCHES_USEABLE)(P_, F_, M_)
#define MATCHED_PATTERN(P_, F_, M_) EAT
Usage
#include <sys/stat.h>
// Match macros (prefix plus flag)
#define STAT_FLAG_UF_NODUMP ,MATCHED_PATTERN
#define STAT_FLAG_UF_IMMUTABLE ,MATCHED_PATTERN
#define STAT_FLAG_UF_APPEND ,MATCHED_PATTERN
// Apply
#define EXPORT_FLAG(FLAG_) \
exports.Set(Napi::String::New(env, #FLAG_), \
Napi::Number::New(env, FLAG_));
Napi::Object Init(Napi::Env env, Napi::Object exports) {
IF_NMATCHES_CALL(STAT_FLAG_,UF_NODUMP,EXPORT_FLAG)(UF_NODUMP)
IF_NMATCHES_CALL(STAT_FLAG_,UF_IMMUTABLE,EXPORT_FLAG)(UF_IMMUTABLE)
IF_NMATCHES_CALL(STAT_FLAG_,UF_APPEND,EXPORT_FLAG)(UF_APPEND)
return exports;
}
Semantically, IF_NMATCHES_CALL takes as arguments a prefix, a flag, and the name of a function-like macro. It will expand to EAT if the pattern matches, or your function-like macro's name if it doesn't. Then you add call arguments; EAT is a variadic macro that swallows those arguments and expands to nothing... your macro does what you want.
A pattern is matched if there is a "pattern-match" macro; the pattern match macro has a name equivalent to the prefix and the flag you're checking, and a replacement list of ,MATCHED_PATTERN (comma is significant, see below).
Mechanism
The core here uses C preprocessor pattern matching via an indirect SECOND macro. By default this macro expands to its second argument; when used as a pattern matcher, you would arrange the first argument to produce a token to be matched; for match cases you define a macro with that name and put a comma in that macro's replacement list, which shifts in a non-default macro.
The top level macro first applies a pattern matcher on parenthesized flag replacement lists; in such cases, IF_NMATCHES_P will expand, shifting IF_NMATCHES_USEABLE. If the flag doesn't expand to a parenthesized list, the second level IF_NMATCHES_D2 is called. This call matches on the prefix/suffix combination (the GLUE here is what would fail if your system defined the flag as a negative literal, as e.g. -1 is not right-pasteable); if your flag is not defined, the result of this would be your match macro, which will shift in MATCHED_PATTERN resulting in the EAT. If your flag is defined, the argument is ignored by the SECOND macro resulting in IF_NMATCHES_USEABLE. IF_NMATCHES_USEABLE is what expands to M_.
Demo
http://coliru.stacked-crooked.com/a/d151d475f2736141

macro expand in c++

Define two macros, as followed:
#define MACRO_COMBINE_INNER(A,B) A##B
#define MACRO_COMBINE(A,B) MACRO_COMBINE_INNER(A,B)
We use these macros
MACRO_COMBINE_INNER(ABC,__LINE__)
MACRO_COMBINE(ABC,__LINE__)
If the current line number is 123, that's LINE == 123, Why the results expand from the two macros are:
ABC__LINE__
ABC123
Order of expansion plays role here, first the outlier macro is expanded, then inner ones. In first case, after expanding MACRO_COMBINE_INNER you get:
ABC##__LINE__
which turns into ABC__LINE__, because __LINE__ is not a separate token here. In second case, preprocessor expands MACRO_COMBINE(ABC,__LINE__), then
__LINE__ is expanded. `
MACRO_COMBINE_INNER(ABC,123)
And then MACRO_COMBINE_INNER is expanded
ABC##123
There is similar behavior with stringify operator, which requires creating macro like this
#define STRINGIFY(x) #x
#define STRING(x) STRINGIFY(x)
To be able use __LINE__ in string literal:
#define THROW_BAD_INDEX(x) throw std::out_of_range \
(__FILE__ ":" STRING(__LINE__) ": Bad index")

Nested macro expansion

I'm not sure if that's the right terminology to use, however my problem is that the a macro call ("PLUGIN_NAME") as a parameter to another macro call ("IMPLEMENT_MODULE"), which in turn prints it as a string, prints that argument as the macro call ("somePLUGIN_NAME") rather than the expanded result ("someSomePluginName").
Note that "IMPLEMENT_MODULE" is an API call so I can't change that.
#define IMPLEMENT_MODULE(name) something##name
#define PLUGIN_NAME SomePluginName
#define _STR(s) #s
#define STR(s) _STR(s)
#define PLUGIN_NAME_STR STR(PLUGIN_NAME)
int main()
{
string expected = "somethingSomePluginName";
string actual = STR(IMPLEMENT_MODULE(PLUGIN_NAME));
printf("expected: %s || actual: %s\n", expected.c_str(), actual.c_str());
assert(expected == actual);
}
I've put it here:
http://codepad.org/FRzChJtD
You need another helper macro to concatenate the preprocessor tokens after macro-expanding them:
#define IMPLEMENT_MODULE_2(A, B) A##B
#define IMPLEMENT_MODULE(name) IMPLEMENT_MODULE_2(something, name)
See working example here
This technical explanation is that macro expansion will not occur if the token-pasting (##) or stringizing operator (#) are found by the preprocessor.

Is there widely-available wide-character variant of `__FILE__`?

One may generally use __LINE__ and __FILE__ in C++ programs, with many toolchains, including GCC.
__LINE__ under GCC evaluates to an expression of type int;
__FILE__ evaluates to a char const[N] where N is the appropriate value.
Does any major toolchain provide an equivalent to __FILE__ with type wchar const[N]?
If so, what is it?
You can make your own WFILE:
#define WIDE2(x) L##x
#define WIDE1(x) WIDE2(x)
#define WFILE WIDE1(__FILE__)
Tested with non-ASCII characters and filename 马克.cpp:
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#define WIDE2(x) L##x
#define WIDE1(x) WIDE2(x)
#define WFILE WIDE1(__FILE__)
int main() {
_setmode(_fileno(stdout), _O_U16TEXT); // required for Unicode output to console
wprintf(L"%s\n", WFILE);
}
Demo (running from cmd.exe and Chinese language support installed):
C:\>cl /W4 /nologo 马克.cpp
马克.cpp
C:\>马克.exe
马克.cpp
Use:
WIDE(MEXPAND(__FILE__))
and
WIDE(STRINGIFY(__LINE__))
or replace __LINE__ with anything that needs to be stringified, and replace __FILE__ with any macro string literal you want to widen.
Using the following definitions:
#define STRINGIFY2(m) #m
#define MEXPAND(m) m
#define STRINGIFY(m) STRINGIFY2(m)
#define WIDE(m) L ## m
Example usage:
#define AssertBreakMethod DebugBreak
#define AssertBreakForce(expr) \
do \
{ \
if (!(expr)) \
{ \
OutputDebugStringW(WIDE(MEXPAND(__FILE__)) \
WIDE("(") WIDE(STRINGIFY(__LINE__)) \
WIDE("): Assertion failed: ") \
WIDE(#expr) WIDE("\n")); \
AssertBreakMethod(); \
} \
} \
while (0)
Note that the whole parameter to OutputDebugString is assembled statically at compile time into a single string literal.
The trick with stringification of a macro is passing it through another macro. When __FILE__ is passed to MEXPAND it is expanded at that time. MEXPAND returns its argument which is now a string. It is then legal to put the leading L there to make it wide.
STRINGIFY does the same trick, it passes its argument through STRINGIFY2 which expands the argument to the line number (which looks like an integer at that point) then STRINGIFY2 puts the # symbol before it, stringifying the integer.
In Visual Studio just surround it with _T(), for example:
TRACE( _T("function = %s"), _T(__FUNCTION__);
I would have put this answer as a comment to an earlier reply but was not allowed due to not having the minimum 50 reputation to comment...
In Visual Studio, _T(__FILE__) will NOT expand to L__FILE__ unless you modify its standard definition of _T in the tchar.h header file. _T(__FILE__) and _T(__FUNCTION__) worked 5 years ago and still work today if you are looking for wide versions of the current file and function.
_T(x) is defined as __T(x), which is defined as L##x when _UNICODE is defined and x otherwise. So _T(__FILE__) expands to something like __T("my_file.c"), which then expands to L"my_file.c" or "my_file.c" depending on _UNICODE. It is useful to test things before claiming that they do not work.
For example use const auto name = L"" __FUNCTION__;

macro NAME expansion as string c/C++

I want use the NAME of the macro inside the macro expansion as string.
Example:
#define DEBUG_TEST(a, ...) printf("DEBUG_TEST::%s (%d) : " a, __FUNCTION__, __LINE__, ##__VA_ARGS__)
Want to change to something that doesn't need the "DEBUG_TEST" anymore in the exapansion, but something like:
#define DEBUG_TEST(a, ...) printf(__MACRO__ "::%s (%d) : " a, __FUNCTION__, __LINE__, ##__VA_ARGS__)
Of course in my example __MACRO__ dosen't exist...
I believe this is not possible. My suggestion would be to create another macro that takes the name of the macro as argument. Then use this macro in your other macroses.