What (if any) are some potential problems with a C++ macro usage like this? Would an inline function be a more appropriate solution?
开发者_高级运维#define EVENT_INFO(_format_, ...) CMyEvent::Generate(__FILE__, __LINE__, CMyEvent::EVT_HIGH, _format_, __VA_ARGS__)
void
CMyEvent::Generate(
const char* file, // filename
int line, // line number
CMyEvent::LEVEL level, // severity level
const char *format, // format of the msg / data
...) // variable arguments
{
// Get a message from the pool
CMyEvent* p_msg = GetMessageFromPool();
if(p_msg != NULL)
{
va_list arguments; // points to each unnamed argument
va_start(arguments, format);
// Fill the object with strings and data.
p_msg->Fill(file, line, level, 0, format, arguments);
va_end(arguments);
}
}
As you're using C++, you can avoid the pitfalls of using variable argument lists which are subject to many problems:
- No check on quantity of arguments
- No check on argument type
To make it more C++, do something like:
#define EVENT_INFO(args) EventLogStream (__FILE__, __LINE__, __PRETTY_FUNCTION__) << args
and invoke it like (warning: all code here is pseudocode and may be syntactically incorrect, but you should get the basic idea):
EVENT_INFO ("The answer to " << the_question << " is " << answer); // usually 42
The EventLogStream is similar to the cout object and like cout, you can provide class specific output:
class Vector3D
{
EventLogStream &operator << (EventLogStream &out) { out << "{" << x << ", " << y << ", " << z << "}"; }
}
If you could rewrite your messaging to use operator<<(), perhaps using std::ostreams with a custom stream buffer, you wouldn't need variable arguments or the ugly (IMHO) macro, and it would look a lot more like C++ than C.
variadic macro is great for use on logging. much better than using iostreams. inline function won't work unless you are willing to pass __FILE__
, __LINE__
manually.
You can enclose format with parentheses for safety (not necessary IMHO)
精彩评论