Undefining functions using preprocessor macros - c++

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?

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.

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.

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
}
};

Related

log C++ class method callers (function name, line number)

I have a class in my C++ code similar to the following:
class myClass
{
public:
void method1(int a, int b, std::string str);
};
Other classes can instantiate an object from myClass and call method1.
void caller()
{
obj1->method1(12, 4, "sample");
}
I want to log all the callers of myClass (function name, file name, line number). One possible solution is this:
class myClass
{
public:
method1(int a, int b, std::string str, const char *_function = __builtin_FUNCTION(), const char *_file = __builtin_FILE(), int _line = __builtin_LINE());
};
which is using __builtin_xxx as default arguments. This solution has multiple shortcomings:
It is an ugly solution
__builtin_xxx is only available in gcc version > 4.8
We have to add three default parameters to method1
IDE shows the default parameters on auto-completion that are not meant to be provided by the user!
Another solution is using __LINE__, __FILE__ and __func__ that is basically very similar to the previous solution. They are not defined outside of function scope, and they should be used like this:
void caller()
{
obj1->method1(12, 4, "sample", __func__, __FILE__, __LINE__);
}
Here is a working example for both solutions.
Is there any better solution to log the caller when the user calls method1 on myClass object. By a better solution I specifically mean not to change the method1's declaration by adding three more parameters!
Another ugly solution, but I'm using...
Use macros to automatically add __LINE__ __FILE__ ...etc. things into parameters.
For example
#define Method(param0,param1) Method(param0,param1,__LINE__)
It has a lot of problem, if you want macros work as normal function, you has to do a lot of things, and it still may not works.
I use it to help me log errors.
Looks like a duplicate of Print the file name, line number and function name of a calling function - C Prog
I'd pass the data to the function through parameters (maybe get the help of a macro)
int info(const char *fname, int lineno, const char *fxname, ...) { /* ... */ }
int debug(const char *fname, int lineno, const char *fxname, ...) { /* ... */ }
int error(const char *fname, int lineno, const char *fxname, ...) { /* ... */ }
And to call them
info(__FILE__, __LINE__, __func__, ...);
debug(__FILE__, __LINE__, __func__, ...);
error(__FILE__, __LINE__, __func__, ...);
Note: __func__ is C99; gcc, in mode C89 has __FUNCTION__

class and pass string as argument to method

How to pass a string to a method in a class?
code
class Txtbin{
private:
std::string input;
std::string output = "output.png";
void error();
public:
Txtbin();
void run();
};
Txtbin::Txtbin(){
}
void Txtbin::error(const char* str){
throw std::runtime_error(str);
}
void Txtbin::run(){
if(input == ""){
error("Input file not defined");
}
}
error
# g++ -std=c++11 txtbin.cpp -o txtbin `pkg-config opencv --cflags --libs`
txtbin.cpp:30:6: error: prototype for ‘void Txtbin::error(const char*)’ does not match any in class ‘Txtbin’
void Txtbin::error(const char* str){
^
txtbin.cpp:14:8: error: candidate is: void Txtbin::error()
void error();
^
As others mentioned, you are declaring void error(); but defining void error(const char* str);. Put const char* str parameter in the declaration too, inside the class.
prototype for ‘void Txtbin::error(const char*)’
does not match any in class ‘Txtbin’
You're trying to define Txtbin's void error(const char*) function, but it does not have one.
candidate is: void Txtbin::error()
It does, however, declare a void error() function, without the parameter. Since you actually use that parameter in the implementation, you probably want to add it to its declaration.
Like others have said, void error() requires no parameter. However later you create void error(const char* str) which has a parameter.
class Txtbin{
private:
string input;
string output = "output.png";
public:
Txtbin();
void error(const char*); //This is what you need.
/* void error(); THIS IS WHAT YOU HAD */
void run();
};
void Txtbin::error(const char* str)
{
//Whatever
}

On using __attribute__((format(printf,

I'm trying to suppress -Wformat-nonliteral warnings. I have used attribute((format(printf with success elsewhere but the following example eludes me.
exceptions.hpp
class Exceptions {
...
static void fthrow(Thread* thread, const char* file, int line, Symbol* name,
const char* format, ...);
};
exceptions.cpp
__attribute__((format(printf, 5, 6)))
void Exceptions::fthrow(Thread* thread, const char* file, int line, Symbol* h_name, const char* format, ...) {
const int max_msg_size = 1024;
va_list ap;
va_start(ap, format);
char msg[max_msg_size];
vsnprintf(msg, max_msg_size, format, ap);
msg[max_msg_size-1] = '\0';
va_end(ap);
_throw_msg(thread, file, line, h_name, msg);
}
result
exceptions.cpp:229:16: error: format argument not a string type
__attribute__((format(printf, 5, 6)))
^ ~
exceptions.cpp:235:32: error: format string is not a string literal [-Werror,-Wformat-nonliteral]
vsnprintf(msg, max_msg_size, format, ap);
^~~~~~
Since it is a static, the exact index should be used, but I've tried 4, 5 and 6, 7 (if out by one) with similar fail.
The attribute should be set on the declaration of the function, not the definition.
class Exceptions {
...
static void fthrow(Thread* thread, const char* file, int line, Symbol* name,
const char* format, ...) __attribute__((format(printf, 5, 6)));
};

Is there any way to handle errors in libxml sax parsing?

I have to use libxml in my c++ code, for some reason and my program is parsing xml files with sax method.Is there any way to handle errors or exceptions in parsing?thanks in advance.
You can write your own error handler like this :
static void my_error(void *user_data, const char *msg, ...) {
va_list args;
va_start(args, msg);
g_logv("XML", G_LOG_LEVEL_CRITICAL, msg, args);
va_end(args);
}
static void my_fatalError(void *user_data, const char *msg, ...) {
va_list args;
va_start(args, msg);
g_logv("XML", G_LOG_LEVEL_ERROR, msg, args);
va_end(args);
}
(example from here)
And register them using xmlSetGenericErrorFunc and xmlSetStructuredErrorFunc.
Example of registration without context :
xmlSetGenericErrorFunc(NULL, my_fatalError);

Win32 program compiler errors in class definition file

I am trying to Compile in Visual C++ and just added this config file loader/parser to my project. For some ever function defined in class CProfileData is receiving at least one of two errors:
missing type specifier - int assumed.
syntax error : missing ',' before '&'
When obviously this should just be a referenced string
#ifdef UVSS_EXPORTS
#define UVSS_API __declspec(dllexport)
#else
#define UVSS_API __declspec(dllimport)
#endif
class CProfileData
{
public:
UVSS_API CProfileData(){};
UVSS_API CProfileData(const string& profileFile);
UVSS_API ~CProfileData(void);
UVSS_API bool GetVariable( const string& sectionName, const string& variableName, string& valueRet );
UVSS_API bool GetSection( const string& sectionName, SECTION_MAP **pMapRet );
UVSS_API bool GetVariableW( const string& sectionName, const string& variableName, wstring& valueRet );
UVSS_API bool GetVariableInt( const string& sectionName, const string& variableName, int *pIntRet );
private:
void ToLower( string& str );
void TrimWhitespace( string& str);
bool IsComment( const string& str );
bool IsSection( const string& str, string& secName );
bool IsVariable( const string& str, string& name, string& value );
PROFILE_MAP m_mapProfile;
};
Include <string>:
#include <string>
And write std::string wherever you've written string.
Its not a good idea to do either of the following in a header file:
using namespace std; //avoid doing this
using std::string; //avoid doing this as well
Ensure that these two lines appear before including this header:
#include <string>
using std::string;