I'm currently working on a cpp logger which aims at displaying the __FILE__ and the __LINE__ before each printed message. In my case, we are mostly using 2 methods for printing out: printf-style and std::cout-style. For the moment I have a macros for each style:
#define HATFormatFatal(...) HATLogger::logFormat(HATLogger::LogLevel::FATAL, __FILE__, __LINE__, __VA_ARGS__)
#define HATFormatError(...) HATLogger::logFormat(HATLogger::LogLevel::ERROR, __FILE__, __LINE__, __VA_ARGS__)
etc... and:
#define HATStreamFatal HATLogger::logStream(HATLogger::LogLevel::FATAL, __FILE__, __LINE__)
#define HATStreamError HATLogger::logStream(HATLogger::LogLevel::ERROR, __FILE__, __LINE__)
These macros can be called in the following:
HATFormatError("This is an %s message", "ERROR");
HATStreamError << "This is an " << "ERROR" << " message" << std::endl;
I would like to call them with the same name: HATLogError. The right macro would be determine at compilation while looking for parenthesis. So far I've seen some examples showing how it is possible to discriminate the macros by the number of arguments, but nothing that could handle a "non-parenthesis" case.
Does anyone have any idea on how this could be achieved ?
The simplest approach would be not overloading the macro at all, but instead having the macro return an object that has both operator<< and operator() overloaded. Something like this:
class error_logger {
public:
error_logger(
HATLogger::LogLevel level,
char const * file,
char const * line
) : level{level}, file{file}, line{line} { }
template <typename... T>
void operator()(T && ... args) {
HATLogger::logFormat(level, file, line, std::forward<T>(args)...);
}
template <typename T>
HATLogger::logStream operator<<(T && arg) {
HATLogger::logStream stream{level, file, line};
stream << std::forward<T>(arg);
return stream;
}
private:
HATLogger::LogLevel level;
char const * file;
char const * line;
};
(This example assumes HATLogger::logStream can be moved. Adjustments to this example implementation may need to be made based on the details of your code, but the basic approach is what I'm demonstrating here.)
Now you could do:
#define HATFormatFatal (error_logger{HATLogger::LogLevel::FATAL, __FILE__, __LINE__})
And then both HATFormatFatal << ... and HATFormatFatal(...) can be used.
Related
I am trying to wrap a #define macro in C++ into an inline or template function. In LOG4CXX it has a define such as:
#define LOG4CXX_INFO(logger, message) { \
if (logger->isInfoEnabled()) {\
::log4cxx::helpers::MessageBuffer oss_; \
logger->forcedLog(::log4cxx::Level::getInfo(), oss_.str(oss_ << message), LOG4CXX_LOCATION); }}
I am needing to add other context to the logs and have wrapped LOG4CXX_INFO in another define and have this implementation working. I am wanting to move away from using a #define to wrap this and do it in a more C++ way. This issue I am running into is that the message param can be of various types of objects concated together using + or << operators and this is currently handled in the MessageBuffer class with operator overrides.
If I try to template it such as:
template<typename T>
void info(LoggerPtr logger, const T& message) {
...do stuff ...
LOG4CXX_INFO(logger, message);
}
The compiler will complain about not finding << operators for various types of objects.
What needs to be done to make this work?
Compiled with the following on ubuntu
gcc main.cpp -lstdc++ -llog4cxx
#include <log4cxx/logger.h>
using namespace std;
#define info(logger, message) LOG4CXX_INFO(logger, message)
template<typename T> void tinfo(log4cxx::LoggerPtr logger, const T& message) {
LOG4CXX_INFO(logger, message);
}
int main()
{
log4cxx::LoggerPtr logger;
LOG4CXX_INFO(logger, "test" << "test2");
info(logger,"another test");
info(logger,"another test" << "another test2");
tinfo(logger,"test template");
//tinfo(logger,"test template" << "test template 2"); -> this line does not compile
return 0;
}
Compiler error:
main.cpp: In function ‘int main()’:
main.cpp:21:31: error: invalid operands of types ‘const char [14]’ and ‘const char [16]’ to binary ‘operator<<’
tinfo(logger,"test template" << "test template 2");
MessageBuffer code can be found here: https://github.com/apache/logging-log4cxx/blob/master/src/main/include/log4cxx/helpers/messagebuffer.h and here https://github.com/apache/logging-log4cxx/blob/master/src/main/cpp/messagebuffer.cpp
tinfo(logger,"test template" << "test template 2");
is wrong. It first evaluates "test template" << "test template 2" and then passes the result to the function. But that makes no sense, since the left-hand side of << should be a stream object.
This works with the macro, because macros are pure text substitution, so the substitution
LOG4CXX_INFO(logger, "test" << "test2");
yields
oss_ << "test" << "test2"
which is evaluated left-to-right.
If you add parentheses around the macro argument
LOG4CXX_INFO(logger, ("test" << "test2"));
you reproduce the function behavior faithfully and you will get the same error because you would be evaluating
oss_ << ("test" << "test2")
If you want to output multiple things in one function call I suggest using a fold expression (available since C++17):
template<typename... Ts>
void tinfo(log4cxx::LoggerPtr logger, const Ts&... messages) {
if (logger->isInfoEnabled()) {
::log4cxx::helpers::MessageBuffer oss_;
logger->forcedLog(::log4cxx::Level::getInfo(), oss_.str((oss_ << ... << messages)), LOG4CXX_LOCATION);
}
}
tinfo(logger, "test template", "test template 2");
If you want to keep the original syntax and/or refer to LOG4CXX_INFO instead of reimplementing the body of that macro, then I don't think it is possible without macros.
The preprocessor has always been black magic to me but I think I finally need to use it.
I have implemented a logger class which I want to conditionally (compile flag) expand to nothing if the flag is not set so that I don't get all my prints in production.
This would have a usecase like so
FO_LOG << name() << "Hello World" << std::endl;
I thought I could define it like this
#ifdef TRACE
#define FO_LOG {return Faceoff::trace::log();}
#else
#define FO_LOG \
if(false){\
return Faceoff::trace::log();\
}
#endif
But this won't compile with the following errors
no viable conversion from returned value of type 'Faceoff::trace' to function return type 'int'
FO_LOG << name() << "omitted" << std::endl;
^~~~~~
/omitted/include/globals.h:69:16: note: expanded from macro 'FO_LOG'
return Faceoff::trace::log();\
^~~~~~~~~~~~~~~~~~~~~
Now the error is clear, but I don't know how to express my intention in preprocessor syntax...
Here you go:
class devnull : public std::ostream {
class devnullbuff : public std::streambuf {
public:
int overflow( int c ) { return c; }
} m_nb;
public:
devnull() : std::ostream( &m_nb ) {}
};
#ifdef TRACE
#define FO_LOG Faceoff::trace::log()
#else
#define FO_LOG devnull()
#endif
Assuming Faceoff::trace::log() returns some sort of ostream, then you can do what you want:
FO_LOG << name() << "Hello World" << std::endl;
This is not quite efficient because it creates a new devnull object every time. You can just create it once in your program and forward declare to it to avoid this. It's not as elegant though.
I have third party C library. I want to use it in c++
Every function return error code.
when i have to use it I have to write code like this:
int err;
err=libFun1(....);
check(err);
err=libFun2(....);
check(err);
I want to wrap this functions and avoid code duplication of check. Every of this librabry function have different number parameters. What will be a good design for this?
How about a templated function:
template <typename T>
int CallWrapper(T func)
{
int error = func();
check(error);
return error;
}
Then call it with CallWrapper(libFun1);.
/edit 4: The C++11-Way using variadic templates, inspired by Gill Bates' solution:
template <typename T, class ...A> int CallWrapper(T func, A... args) {
int error = func(args...);
check(error);
return error;
}
CallWrapper(libFun1);
CallWrapper(libFun2, 4711);
CallWrapper(libFun3, 42, 23);
/edit 5: older solutions, beginning with first solution:
#define LIBFUN1() do { \
int err = libFun1(); \
check(err); \
} while (0)
#define LIBFUN2() do { \
int err = libFun2(); \
check(err); \
} while (0)
LIBFUN1();
LIBFUN2();
Put the #defines in some header file. Please note the MISSING semicolon after the while (). This way, you can naively use LIBFUN1() and so on in any context, where a statement is allowed like if (...) LIBFUN1(); else LIBFUN2();
/edit 3: Instead of using #defines, static inline functions would do the job too:
static inline int checked_libFun1() {
int err = libFun1();
check(err);
return err;
}
static inline int checked_libFun2() {
int err = libFun2();
check(err);
return err;
}
checked_libFun1();
checked_libFun2();
/edit 2: #Myst suggested to use variadic macros that contain the name of the function to call. This could look like this:
#define call_void(name) do { \
int err = name(); \
check(err); \
} while (0)
#define call_args(name, ...) do { \
int err = name(__VA_ARGS__); \
check(err); \
} while (0)
call_void(libFun1);
call_args(libFun2, 42);
The two macros are needed because you have to distinguish between functions not accepting any arguments and functions accepting any number of arguments greater one. So, here, libFun2(42) would be called
You can use exceptions and catch them.
One way is to use Macros like:
#include <exception>
#define THROW_ON_ERROR(libFunc) do{ \
int err = libFunc(); \
if(check(err)) \
throw std::exception(); \
}while(0); \
and you code will look like this:
try
{
THROW_ON_ERROR(libFun1);
THROW_ON_ERROR(libFun2);
}catch(const std::exception& e)
{
//handle...
}
This method is not very modern but does the job. It was just to pass the point of converting the error status code convention which is the common way in C to exception handling which is a nice way in C++ (not sure if common).
Also you can use your own exceptions to pass some data.
You can do the same thing by calling a function like:
#include <functional>
class LibFuncException : public std::exception
{
public:
explicit LibFuncException(int err) : m_err(err) {}
int GetError() const { return m_err; }
private:
int m_err;
};
void ThrowOnError(std::function<int()> libFunc)
{
int err = libFunc();
if(check(err)
throw LibFuncException(err);
}
and your code can:
try{
ThrowOnError(libFunc1);
ThrowOnError(libFunc2);
} catch(const LibFuncException& e)
{
std::cout << "Error: << e.GetError() << std::endl;
}
EDIT:
if your library function sometime receive arguments you can either call the ThrowOnError with a lambda like so:
int x = 10;
const char* str = "Hello World";
ThrowOnError([x, str]() { return libFuncWithArgs(x, str); });
Or if you want to be extreme you can have a variadic template like someone suggested already
From given code, you may simply write
check(libFun1(/*...*/));
check(libFun2(/*...*/));
Possibly, you may want to wrap each method to have only one call from user side:
void chekedLibFun1(/*...*/) { check(libFun1(/*...*/)); }
void chekedLibFun2(/*...*/) { check(libFun2(/*...*/)); }
and so previous code becomes:
checkedLibFun1(/*...*/);
checkedLibFun2(/*...*/);
I can see a few ways to do this:
Template functions (#GillBates has you covered).
An inline function (maybe with variadic arguments).
Simple macros (#usr and #ZivS have you covered).
A variadic Macro.
Since you're writing for C++, I'd probably use Template functions... the only thing negative about that option is that function argument handling (assuming the library functions accept arguments) could be a headache.
I think the C approach of a variadic Macro would work better, also providing compile-time unwrapping (vs. runtime unwrapping).
i.e. (this is only an example, I didn't even test the code)
int checkerr(int err) {
if(!err)
return 0;
// ... handle errors, exit if need be.
}
#define CALL_CLIB(fn_name, ...) checkerr((fn_name)(__VA_ARGS__))
You can use it like so:
// will print "this is only 1 example"
CALL_CLIB(printf, "this is only %d, %s", 1, "example");
You can make it also more complex, if you want, adding try, catch or whatever you want into the mix.
I have a question. In one of my projects i am using the FLAG PRINT to enable/disable the debug printfs. currently I am using something like this.
#ifdef PRINT
printf("DEBUG");
#endif
It is a pain to put this #ifdef before every printf. So I was thinking to 've a #define for the #ifdef, something like
#define DEBUG_PRINT
#define PRINT (#ifdef DEBUG_PRINT)
#define ENDPRINT #endif
so that I can use like
PRINT
printf("DEBUG");
ENDPRINT
but it is giving a compiler error. Can you tell me someway to simplify.
Thanks,
A standard way is
#ifdef DEBUG_PRINT
# define is_debug() (1)
#else
# define is_debug() (0)
#endif
#define pr_dbg(fmt, ...) do { \
if (is_debug()) \
printf(fmt, __VA_ARGS__); \
} while (0)
When using gcc, you can/should write
printf(fmt, ## __VA_ARGS__);
to deal with empty args.
In your code you can write then
pr_dbg("foo=%u\n", foo);
Optimizer will throw away the expression when DEBUG_PRINT is not defined but your debug statements will be still checked for syntax errors. This avoids silent breakage when e.g. undefined variables are used within an #ifdef clause.
How about a header with
#ifdef DEBUG
#define ON_DEBUG(X,...) do { X, __VA_ARGS__; } while( false )
#else
#define ON_DEBUG(X,...) do {} while( false )
#endif
and in your code, you simply use
ON_DEBUG( printf("Hallo, %s", "Welt") );
(the do-while forces you to add the final semicolon and protects the statement's in cases if (nested) if-statements, see Aaron McDaid's comment)
I would actually do it a different way entirely. First define the flag that turns printing on or off:
// uncomment to turn off debug printing
#define DEBUG_PRINT 1
Then conditionally define your printer macro depending of the definition state of DEBUG_PRINT:
#ifdef DEBUG_PRINT
#define PRINT (X) (printf(x))
#else
#define PRINT (x)
#endif
Which can be used simply as:
PRINT("foo");
But in reality, I wouldn't do any of this stuff at all. Instead, I'd have the turn-on/turn-off flag as above, and then build a class that does the printing:
// comment out to not do debug printing
//#define DEBUG_PRINTING 1
#ifdef DEBUG_PRINTING
class Printer
{
public:
Printer() {}
~Printer()
{
std::cout << mOutput.str() << "\n";
}
template <typename TYPE> Printer& operator<< (const TYPE& val)
{
mOutput << val;
return * this;
}
template <size_t N> Printer& operator<< (const char(&ary)[N])
{
mOutput << ary;
return * this;
}
private:
std::stringstream mOutput;
};
#else
class Printer
{
public:
Printer() {};
template <typename TYPE> Printer& operator<< (const TYPE& val)
{
return * this;
}
template <size_t N> Printer& operator<< (const char(&ary)[N])
{
return * this;
}
};
#endif
int main()
{
Printer() << "My output here. " << 42;
}
In optimized builds where the flag is not defined, most (if not all) of the code will be optimized away.
I was trying the logger code from this link, but it gives me error. How to implement a good debug/logging feature in a project
#ifndef _LOGGER_HPP_
#define _LOGGER_HPP_
#include <iostream>
#include <sstream>
/* consider adding boost thread id since we'll want to know whose writting and
* won't want to repeat it for every single call */
/* consider adding policy class to allow users to redirect logging to specific
* files via the command line
*/
enum loglevel_e
{logERROR, logWARNING, logINFO, logDEBUG, logDEBUG1, logDEBUG2, logDEBUG3, logDEBUG4};
class logIt
{
public:
logIt(loglevel_e _loglevel = logERROR) {
_buffer << _loglevel << " :"
<< std::string(
_loglevel > logDEBUG
? (_loglevel - logDEBUG) * 4
: 1
, ' ');
}
template <typename T>
logIt & operator<<(T const & value)
{
_buffer << value;
return *this;
}
~logIt()
{
_buffer << std::endl;
// This is atomic according to the POSIX standard
// http://www.gnu.org/s/libc/manual/html_node/Streams-and-Threads.html
std::cerr << _buffer.str();
}
private:
std::ostringstream _buffer;
};
extern loglevel_e loglevel;
#define log(level) \
if (level > loglevel) ; \
else logIt(level)
#endif
More precisely, this #define is giving errors:
#define log(level) \
if (level > loglevel) ; \
else logIt(level)
The errors are Syntax error: if and Syntax error: else
But later, I noticed that if I move #include "logger.hpp" from main.h to main.cpp, the problem disappeared. Though 'main.h' is included many times in different places, it does contain '#pragma once'.
Any idea?
If loglevel is known at compile time you can do the following:
template <bool>
struct LogSystem
{
template <class T>
LogSystem& operator << (const T &)
{
//ignore the input
return (*this);
}
};
template <>
struct LogSystem <true>
{
template <class T>
LogSystem& operator << (const T & v)
{
cout << v;
return (*this);
}
};
template <bool B>
LogSystem<B> getLog()
{
return LogSystem<B>();
}
#define log(level) getLog< (level <= loglevel) >()
if loglevel is not known at compile time:
class iLogSystem
{
public:
virtual iLogSystem& operator << (const int &)
{
//empty
return (*this);
}
virtual iLogSystem& operator << (const custom_type &);
{
return (*this);
}
//make functions for logging all the types you want
};
class LogSystem : public iLogSystem
{
public:
virtual iLogSystem& operator << (const int & v)
{
cout << v;
return (*this);
}
virtual iLogSystem& operator << (const custom_type & q);
{
cout << q.toString();
return (*this);
}
//make functions for logging all the types you want
};
iLogSystem& getLog(const bool l)
{
static LogSystem actual_log;
static iLogSystem empty_log;
if(l)
return &actual_log;
return &empty_log;
}
#define log(level) getLog( level <= loglevel )
Any time you want to define a macro that expands to a statement, if the definition contains any compound statements (including if/else), you should wrap the definition in do ... while (0). The enclosed code will still execute exactly once, and it can be used in any context that requires a statement.
That's the only way I know of to avoid syntax errors when the macro is used within an if/else statement, due to the use of semicolons.
So rather that this:
#define log(level) \
if ((level) > loglevel) ; \
else logIt(level)
you can use this:
#define log(level) \
do { \
if ((level) > loglevel) ; \
else logIt(level) \
} while (0)
I've added parentheses around references to the macro's level parameter, to avoid any possible operator precedence problems. Note also the lack of a semicolon at the end; the semicolon will be supplied by the caller.
On the other hand, an if/else can often be replaced by the conditional (ternary) ?: operator:
#define log(level) \
((level) > loglevel ? 0 : logIt(level))
which allows log(level) to be used anywhere an expression can be used; that includes statement context if you add a semicolon. You might want to replace 0 by something of the type returned by logIt; if logIt is a void function, you might want:
#define log(level) \
((level) > loglevel ? (void)0 : logIt(level))
This all assumes that a macro is the right tool for the job. It's likely that a template (as suggested by this answer) or an inline function will do the job better and with less potential for confusion.
Can #define preprocessor directive contain if and else?
Yes.
Regarding your problem: preprocessor is dumb as a rock and performs only simple text subsitution. It is not a function, it is not a language construct, it is simple, dumb text subsitution. As a a result, this:
#define log(level) \
if (level > loglevel) ; \
else logIt(level)
...
log(logINFO) << "foo " << "bar " << "baz";
Turns into this:
if (logINFO > loglevel); // << here's your problem.
else
logIt(logInfo)
<< "foo " << "bar " << "baz";
Your problem is;. Here, semicolon indicates end of c++ if statement, so when compiler encounters else afterwards, it doesn't know what to do with it.
I noticed that if I move #include "logger.hpp" from main.h to main.cpp, the problem disappeared
C++ has "logarithm" function. Which is called log. If your other files use logarithm function, things will get very interesting, because it'll be replaced by your if/else logging code everywhere.
For example, if there's inlined logarithm code somewhere in a header, it'll turn into nonsense if you include your logger header first. For example log(6.0) + 1 will turn into log (if (6.0 > logLevel); else logIt(6.0)) + 1, which is not a valid C++ statement.