开发者

C\C++ Preprocessor different arg for overloaded macros

I want to realize logging in my project. I have macro, smth like

__LOG_TRACE(lg, expr,...) LOG_TRACE_STREAM(lg) <&开发者_JAVA百科lt; expr;

So I want to realize interface for this macro - another macro, but I want to support 2 types:

LOG_TRACE(msg);
LOG_TRACE(my_logger, msg);

I have some global logger, and first macro will write msg using global logger. Second macro will take my_logger and write msg using it.

I can make it with LOG_TRACE(msg, my_logger); - but it's not good, it's harder to read in code. Order of arguments in __LOG_TRACE is not necessary.

Upd: I don't mean overloading macros. Look - for example I can do this

#define LOG_TRACE(...) __LOG_TRACE(__VA_ARGS__, current_active)

Now I can write

LOG_TRACE(msg);
LOG_TRACE(msg, logger);

But I want not msg,logger and logger,msg


Macro overloading is not allowed in C or C++. But there are workarounds. Here's an article that will help you "overload" your macro: http://cplusplus.co.il/2010/08/31/overloading-macros/


If you don't have a variable number of loggers, i recommend you to make a macro for each logger. ex (LOG_TRACE_XML, LOG_TRACE_OUT, LOG_TRACE_TXT). Because simpler is better.

But a better way to do this is to have LOG_TRACE_ERROR/ LOG_TRACE_WARNING/ LOG_TRACE_INFO and manage the way these macros behave using IPC or another macro (SET_MODE(XML/TXT/OUT))


You cannot overload pre-processor macros, your compiler will consider this a redeclaration, rather than an overload, and so only the 2nd will be valid.

You should attempt to name your macros differently, both for readability and because that's the only way you'll get the functionality you want.


Why not make it a function + do and stringify expression macro?

#define DO_AND_RETURN_STRING_EXPR(x) (x,#x)

ov(DO_AND_RETURN_STRING_EXPR(y))
ov(my_logger, DO_AND_RETURN_STRING_EXPR(y))

(note I haven't tested this code).


__VA_ARGS__ is an extension to the current C++ standard, but if you are willing to play with this P99 has a lot of utility macros to achieve what you want. In particular macros that implement conditionals according to the number of arguments they are called.

#define LOG_TRACE(...)                    \
P99_IF_EQ_1(P99_NARG(__VA_ARGS__))        \
(LOG_TRACE_(my_logger, __VA_ARGS__))      \
(LOG_TRACE_(__VA_ARGS__))

P99 is not really C++ compatible, so you'd have to adapt things a bit.

BTW, identifiers that start with _ and a capital letter or another underscore are reserved by C and C++. Double underscores in general are not allowed for C++ because they could interfere with name mangling. So you'd better chose a different name for your base macro.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜