Reputation: 7184
I've a log system written in C++ with this type of functions to write on it:
void processMessages();
void DEBUG_MSG(const std::string& appender,const char* msg, ...);
void INFO_MSG(const std::string& appender,const char* msg, ...);
void WARNING_MSG(const std::string& appender, const char* msg, ...);
void ERROR_MSG(const std::string& appender, const char* msg, ...);
void FATAL_MSG(const std::string& appender, const char* msg, ...);
I want to disable via macros in C++. I've read this thread: Disable functions using MACROS but
#ifdef GLOG_SILENCE
#define processMessages (void)sizeof
#define DEBUG_MSG (void)sizeof
#define INFO_MSG (void)sizeof
#define WARNING_MSG (void)sizeof
#define ERROR_MSG (void)sizeof
#define FATAL_MSG (void)sizeof
#else //GLOG_SILENCE
void processMessages();
void DEBUG_MSG(const std::string& appender,const char* msg, ...);
void INFO_MSG(const std::string& appender,const char* msg, ...);
void WARNING_MSG(const std::string& appender, const char* msg, ...);
void ERROR_MSG(const std::string& appender, const char* msg, ...);
void FATAL_MSG(const std::string& appender, const char* msg, ...);
#endif //GLOG_SILENCE
doesn't work properly. I keep getting errors like:
In file included from ../src/test_core.cpp:2:
../src/test_Log.h: In member function ‘virtual void LogTestFixtureTest_defining_SILENCE_macro_avoids_write_and_processing_activity_from_log_Test::TestBody()’: ../src/test_Log.h:63: error: expected unqualified-id before ‘(’ token ../src/test_Log.h:63: error: expected primary-expression before ‘void’ ../src/test_Log.h:63: error: expected ‘;’ before ‘sizeof’ ../src/test_Log.h:64: error: expected unqualified-id before ‘(’ token ../src/test_Log.h:64: error: expected primary-expression before ‘void’ ../src/test_Log.h:64: error: expected ‘;’ before ‘sizeof’
I suspect that the problem is related with the fact that Log is a class, but I don't know how to do it. Some help?
Upvotes: 1
Views: 1494
Reputation: 4184
I would like to suggest you to work in a different way. Just declare the interface ILogger after that implement it in the different loggers, like
class ILogger{
public:
virtual void DEBUG_MSG(const std::string& appender,const char* msg, ...);
virtual void INFO_MSG(const std::string& appender,const char* msg, ...);
virtual void WARNING_MSG(const std::string& appender, const char* msg, ...);
virtual void ERROR_MSG(const std::string& appender, const char* msg, ...);
virtual void FATAL_MSG(const std::string& appender, const char* msg, ...);
virtual ~ILogger(){}
};
For the file logger
class FileLogger : public ILogger{
public:
void DEBUG_MSG(const std::string& appender,const char* msg, ...){....}
void INFO_MSG(const std::string& appender,const char* msg, ...){....}
void WARNING_MSG(const std::string& appender, const char* msg, ...){....}
void ERROR_MSG(const std::string& appender, const char* msg, ...){....}
void FATAL_MSG(const std::string& appender, const char* msg, ...){....}
virtual ~EmptyLogger(){}
};
and the empty logger like:
for the empty logger
class EmptyLogger : public ILogger{
public:
void DEBUG_MSG(const std::string& appender,const char* msg, ...){do nothing here}
void INFO_MSG(const std::string& appender,const char* msg, ...){do nothing here}
void WARNING_MSG(const std::string& appender, const char* msg, ...){do nothing here}
void ERROR_MSG(const std::string& appender, const char* msg, ...){do nothing here}
void FATAL_MSG(const std::string& appender, const char* msg, ...){do nothing here}
virtual ~FileLogger(){}
};
after that in the place where you create the logger could be a factory make a macros in order to generate a different type of logger.
class LoggerFactory{
public:
static ILogger* getLogger(/*loggertype as argument*/){
#ifdef GLOG_SILENCE
/* create a normal logger*/
#else
return new EmptyLogger();
#endif
}
};
Upvotes: 0
Reputation: 409432
If your compiler support variadic macros you can simply define macros with empty replacements:
#ifdef GLOG_SILENCE
#define processMessages(_1, _2, ...)
#define DEBUG_MSG(_1, _2, ...)
#define INFO_MSG(_1, _2, ...)
#define WARNING_MSG(_1, _2, ...)
#define ERROR_MSG(_1, _2, ...)
#define FATAL_MSG(_1, _2, ...)
#else //GLOG_SILENCE
void processMessages();
void DEBUG_MSG(const std::string& appender,const char* msg, ...);
void INFO_MSG(const std::string& appender,const char* msg, ...);
void WARNING_MSG(const std::string& appender, const char* msg, ...);
void ERROR_MSG(const std::string& appender, const char* msg, ...);
void FATAL_MSG(const std::string& appender, const char* msg, ...);
#endif //GLOG_SILENCE
However, this will only work if the functions are NOT members of a class or a namespace, but true global functions.
Upvotes: 0
Reputation: 254701
Indeed, if these are member functions, then the "silent" versions will expand to nonsense:
log.(void)sizeof(stuff);
You could define a member function that does nothing, and macros that swallow their arguments:
void nothing() {}
#define processMessages(...) nothing()
then using the "silent" versions will give valid code that should compile away to nothing:
log.nothing();
The disadvantages of this are (a) you're relying on the compiler to inline the empty function, and not generate a function call; (b) the arguments' syntax is not checked when compiling in silent mode.
Upvotes: 4