Is there any idiom that forces a semicolon after a cpp macro outside of a function?
The known solution for macros used inside functions is:
#define MACRO(x) \
do {
x * 2;
} while(0)
However, say I have a macro that looks like the following:
#define DETAIL(warning) _Pragma(#warning)
#define WARNING_DISABLE(warning) DETAIL(GCC diagnostic ignore warning)
What can I put in the macro that would force a semi-colon after that statement. The statement could be used in or outside of a function:
WARNING_DISABLE("-Wunused-local-typedefs")
#include "boost/filesystem.hpp"
void foo(const int x) {
WARNING_DISABLE("-Wsome-warning")
...
}
Is there any C/C++ syntax that will force a semi-colon in the parser at any point in a file that doesn't have side effects?
Edit: A possible use case:
#define MY_CPPUNIT_TEST_SUITE(test_suite_class) \
WARNING_PUSH \
/* the declaration of the copy assignment operator has been suppressed */ \
INTEL_WARNING_DISABLE(2268) \
/* the declaration of the copy assignment operator has been suppressed */ \
INTEL_WARNING_DISABLE(2270) \
/* the declaration of the copy constructor operator has been suppressed */ \
INTEL_WARNING_DISABLE(2273) \
CPPUNIT_TEST_SUITE(test_suite_class); \
WARNING_POP \
/* force a semi-colon */ \
UDP_KEYSTONE_DLL_LOCAL struct __udp_keystone_cppunit_test_suite ## __LINE__ {}
You don't need LINE trick - it is enough to forward-declare some structure, which is allowed multiple times and there is no need for actual definition. Also collision with actual struct should not be a problem.
#define DETAIL(warning) _Pragma(#warning) struct dummy
#define DETAIL(warning) _Pragma(#warning) struct X ## __LINE__ {}
The easiest is an extern function declaration
#define MACRO_END_(LINE) extern void some_inprobable_long_function_name ## LINE(void)
#define MACRO_END MACRO_END_(__LINE__)
the line trick is only there because some compilers with excessive warnings give you warnings on duplicate declarations.
This macro works in any context where a declaration is allowed, so with C99 almost everywhere:
#define DETAIL(warning) _Pragma(#warning) MACRO_END
Related
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
Trying to avoid write a repeating code; I used macros to delare methods into a class.
I want to define a macro function into header file like :
cracker.h
#include<message.h>
class Cracker {
#define DECLARE_MSG(MSG_NAME, MSG_TYPE,ALREADY_DEFINED) \
{ \
if(!ALREADY_DEFINED)
{ \
virtual bool cbProcessMsg_##MSG_NAME (API::MSG_NAME##Msg const & msg); \
}\
#include "message.h"
#undef DECLARE_MSG
};
message.h
DECLARE_MSG(AddOrder , 'A', false);
DECLARE_MSG(DeleteOrder , 'B', true);
DECLARE_MSG(ReplaceOrder , 'C', false);
...
But this code does note compile because I have not the right to add if statement outside a function.
Is there any alternative to do that ?
There's a couple of items worth highlighting:
1.
Macros do not know scope; the only way you can remove it's definition is to undefine it.
2.
macros are pasted into the code as is; and then compiled. A macro isn't a function itself, it's a code generation tool. This means that even if 'ALREADY_DEFINED' is true, you'll get another definition.
3.
What you're trying to do is add a function into the class outside of the class definition. You just can't do this. Ever.
4.
Header guards will save you pain for medium to large projects; you should get into the habbit of using them early.
While not quite the same, what it looks like you want to do is look up what the factory pattern is.
Use BOOST_PP_IIF if you (can) use the boost-library:
#define DECLARE_MSG(MSG_NAME, MSG_TYPE,ALREADY_DEFINED) \
BOOST_PP_IIF(ALREADY_DEFINED,, \
virtual bool cbProcessMsg_##MSG_NAME (API::MSG_NAME##Msg const & msg); \
)
You should use 0 and 1 instead of false and true here.
But if you don't, you can 'branch' definitions by concating name and number to another macro:
// two definitions for PP_CONCAT to expand macros, etc...
#define PP__CONCAT(a, b) a ## b
#define PP_CONCAT(a, b) PP__CONCAT(a, b)
// to expand your macro you should pass it through another macro
#define PP_EXPAND(...) __VA_ARGS__
#define DECLARE_MESSAGE_0(MSG_NAME, MSG_TYPE) /** the def when ALREADY_DEFINED = 0 */
#define DECLARE_MESSAGE_1(MSG_NAME, MSG_TYPE) /** the other branch */
#define DECLARE_MESSAGE(MSG_NAME, MSG_TYPE, ALREADY_DEFINED) \
PP_EXPAND(PP_CONCAT(DECLARE_MESSAGE_, ALREADY_DEFINED)(MSG_NAME, MSG_TYPE))
When you have problems understanding the preprocessor, you should check out the output with the option -E / running the code with the command cpp(which stands for c-preprogressor and not cplusplus(->c++))
However there may be another way to do the same thing, with templates and inheritance...
For example, I saw source code like the following. Can we use #define in a function? How does it work? (more information: this code is what I copied from openvswitch source code):
void *
ofputil_put_action(enum ofputil_action_code code, struct ofpbuf *buf)
{
switch (code) {
case OFPUTIL_ACTION_INVALID:
#define OFPAT13_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) case OFPUTIL_##ENUM:
#include "ofp-util.def"
OVS_NOT_REACHED();
#define OFPAT10_ACTION(ENUM, STRUCT, NAME) \
case OFPUTIL_##ENUM: return ofputil_put_##ENUM(buf);
#define OFPAT11_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \
case OFPUTIL_##ENUM: return ofputil_put_##ENUM(buf);
#define NXAST_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \
case OFPUTIL_##ENUM: return ofputil_put_##ENUM(buf);
#include "ofp-util.def"
}
OVS_NOT_REACHED();
}
#define OFPAT10_ACTION(ENUM, STRUCT, NAME) \
void \
ofputil_init_##ENUM(struct STRUCT *s) \
{ \
memset(s, 0, sizeof *s); \
s->type = htons(ENUM); \
s->len = htons(sizeof *s); \
} \
\
struct STRUCT * \
ofputil_put_##ENUM(struct ofpbuf *buf) \
{ \
struct STRUCT *s = ofpbuf_put_uninit(buf, sizeof *s); \
ofputil_init_##ENUM(s); \
return s; \
}
#define OFPAT11_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \
OFPAT10_ACTION(ENUM, STRUCT, NAME)
#define OFPAT13_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \
OFPAT10_ACTION(ENUM, STRUCT, NAME)
#define NXAST_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \
void \
ofputil_init_##ENUM(struct STRUCT *s) \
{ \
memset(s, 0, sizeof *s); \
s->type = htons(OFPAT10_VENDOR); \
s->len = htons(sizeof *s); \
s->vendor = htonl(NX_VENDOR_ID); \
s->subtype = htons(ENUM); \
} \
\
struct STRUCT * \
ofputil_put_##ENUM(struct ofpbuf *buf) \
{ \
struct STRUCT *s = ofpbuf_put_uninit(buf, sizeof *s); \
ofputil_init_##ENUM(s); \
return s; \
}
#include "ofp-util.def"
#define is a preprocessor directive: it is used to generate the eventual C++ code before it is handled to the compiler that will generate an executable. Therefore code like:
for(int i = 0; i < 54; i++) {
#define BUFFER_SIZE 1024
}
is not executed 54 times (at the preprocessor level): the preprocessor simply runs over the for loop (not knowing what a for loop is), sees a define statement, associates 1024 with BUFFER_SIZE and continues. Until it reaches the bottom of the file.
You can write #define everywhere since the preprocessor is not really aware of the program itself.
Sure this is possible. The #define is processed by the preprocessor before the compiler does anything. It is a simple text replacement. The preprocessor doesn't even know if the line of code is inside or outside a function, class or whatever.
By the way, it is generally considered bad style to define preprocessor macros in C++. Most of the things they are used for can be better achieved with templates.
You can use it inside a function, but it is not scoped to the function. So, in your example, the second definitions of a macro will be a redefinition and generate an error. You need to use #undef to clear them first.
You can use #define anywhere you want. It has no knowledge of functions and is not bound by their scope. As the preprocessor scans the file from top-to-bottom it processes #defines as it sees them. Do not be misled (by silly code like this!) into thinking that the #define is somehow processed only when the function is called; it's not.
How does it work? All C/C++ files are first processed by... the preprocessor.
It doesn't know anything about C nor C++ syntax. It simply replaces THIS_THING with ANOTHER THING. That's why you can place a #define in functions as well.
Sure. #define is handled by the preprocessor which occurs well before the compiler has any sense of lines of code being inside functions, inside parameters lists, inside data structures, etc.
Since the preprocessor has no concept of C++ functions, it also means that there is no natural scope to macro definitions. So if you want to reuse a macro name, you have to #undef NAME to avoid warnings.
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.
#include < iostream >
#define MY_CHK_DEF(flag) \
#ifdef (flag) \
std::cout<<#flag<<std::endl; \
#else \
std::cout<<#flag<<" ,flag not define"<<std::endl; \
#endif
int main()
{
MY_CHK_DEF(FLAG_1);
MY_CHK_DEF(FLAG_2);
MY_CHK_DEF(FLAG_3);
...
}
complier report:
main.cpp:3:24: error: '#' is not followed by a macro parameter
any ideas?
Thanks
You can't do it. #if, #else, and #endif must be the first tokens on the logical line. Your definition is just one logical line, so it doesn't work,
You have to do it the other way round(defining the macro for each #if/#ifdef/#else condition(if you nest you have to put a definition on each branch). You probably should define it at every logical branch or it will fail to compile when you try to adjust a rarely adjusted flag. You can #define noops like this. Note to be careful not to wrap expressions with side effects into #define 'd macros that reduce to a noop when the debug flag is on, or your program may not work right.
#define N(x)
#include < iostream >
#ifdef (flag)
#define MY_CHK_DEF(flag)
std::cout<<#flag<<std::endl;
#else
#define MY_CHK_DEF(flag) \
std::cout<<#flag<<" ,flag not define"<<std::endl;
#endif
int main()
{
MY_CHK_DEF(FLAG_1);
MY_CHK_DEF(FLAG_2);
MY_CHK_DEF(FLAG_3);
...
}
C preprocessor is single-pass and #define creates a pretty dumb replacement that isn't further processed - your MY_CHK_DEF(flag) macro inserts the #if statement inline into preprocessed code that is interpreted by C compiler and not valid C.
You can either rephrase it to be one-pass, or if you can't, run through preprocessor twice, manually - once through cpp -P and the second time through normal compilation process.
You actually can do this if you use BOOST processor header lib.. it provides a BOOST_PP_IF macro allow this type of decisions.
http://www.boost.org/doc/libs/1_53_0/libs/preprocessor/doc/ref/if.html