Suppose I have the following macro:
#define LOG(L, ...) func(L, __VA_ARGS__);
Where L can be one of INFO, WARN, FATAL
Now I want to define it for FATAL differently.
#define LOG(FATAL, ...) {func(FATAL, __VA_ARGS__); exit(-1);}
How to accomplish this?
Edit:
As a follow up to above, is there a better way to do it? i.e. by avoiding macros for example.
Macros are mostly a bad choice in C++ – essentially because of they are namespace agnostic and may take effect where it is unexpected.
That said – a sample for how OPs issue could be solved e.g. using token pasting:
#include <iostream>
#define LOG(LEVEL, ...) LOG_##LEVEL(__VA_ARGS__)
#define LOG_INFO(...) log(Info, __VA_ARGS__)
#define LOG_WARN(...) log(Warn, __VA_ARGS__)
#define LOG_FATAL(...) do { log(Error, __VA_ARGS__); std::cerr << "Program aborted!\n"; } while (false)
enum Level { Info, Warn, Error };
void log(Level level, const char *text)
{
static const char *levelText[] = { "INFO", "WARNING", "ERROR" };
std::cerr << levelText[level] << ": " << text << '\n';
}
int main()
{
LOG(INFO, "Everything fine. :-)");
LOG(WARN, "Not so fine anymore. :-|");
LOG(FATAL, "Things became worst. :-(");
}
Output:
INFO: Everything fine. :-)
WARNING: Not so fine anymore. :-|
ERROR: Things became worst. :-(
Program aborted!
Live Demo on coliru
Another sample for the follow-up question - with variadic templates instead of macros:
#include <iostream>
enum Level { Info, Warn, Error, Fatal };
template <typename ...ARGS>
void log(Level level, ARGS&& ... args)
{
static const char *levelText[] = { "INFO", "WARNING", "ERROR", "FATAL" };
std::cerr << levelText[level] << ": ";
(std::cerr << ... << args);
std::cerr << '\n';
if (level == Fatal) std::cerr << "Program aborted!";
}
int main()
{
log(Info, "Everything fine.", ' ', ":-)");
log(Warn, "Not so fine anymore.", ' ', ":-|");
log(Error, "Things became bad.", ' ', ":-(");
log(Fatal, "Things became worst.", ' ', "XXX");
}
Output:
INFO: Everything fine. :-)
WARNING: Not so fine anymore. :-|
ERROR: Things became bad. :-(
FATAL: Things became worst. XXX
Program aborted!
Live Demo on coliru
I must admit that I needed some help for the parameter unpacking – found here:
SO: What is the easiest way to print a variadic parameter pack using std::ostream?.
Extending Scheffs answer a bit, this one passes the log level as a template argument, allowing the use of if constexpr (as JVApen mentioned in his comment). You'd need to know the respective level for each log output at compile time, but I think that won't be an issue.
enum Level { Info, Warn, Error, Fatal };
template<Level L, typename ...ARGS>
void log(ARGS&& ... args)
{
static const char *levelText[] = { "INFO", "WARNING", "ERROR", "FATAL" };
std::cerr << levelText[L] << ": ";
(std::cerr << ... << args);
std::cerr << '\n';
if constexpr (L == Fatal)
std::cerr << "Program aborted\n";
}
Related
I have a little error function that looks like this:
template<typename ErrorType>
void throwError(const std::string &file,
const std::string &function,
unsigned int line,
const std::string &msg = "") {
std::ostringstream errMsg;
errMsg << file << ":" << line << ":" << function << ":"
<< "\nError: " << msg << std::endl;
std::cerr << errMsg.str();
throw ErrorType(errMsg.str());
}
Then I have some macros that use the function:
#define INVALID_ARGUMENT_ERROR(msg) throwError<std::invalid_argument>(__FILE__, __func__, __LINE__, msg)
#define LOGIC_ERROR(msg) throwError<std::logic_error>(__FILE__, __func__, __LINE__, msg)
So I can do:
if (condition == bad)
LOGIC_ERROR("you did a bad");
But this is quite invonvenient when I want to add additional information in the error message, like values of numbers for example.
What would be a good way of modifying this function so that it enables me to use a stream instead of a string? So I want do be able to do:
if (condition == bad)
LOGIC_ERROR("you did a bad because condition \"" << condition << " != " << bad);
I've tried changing the std::string string msg to a std::ostringstream which does not work.
If you're willing to change the syntax slightly then a simple helper macro could be used. Given your current function template...
template<typename ErrorType>
void throwError(const std::string &file,
const std::string &function,
unsigned int line,
const std::string &msg = "")
{
std::ostringstream errMsg;
errMsg << file << ":" << line << ":" << function << ":"
<< "\nError: " << msg << std::endl;
std::cerr << errMsg.str();
throw ErrorType(errMsg.str());
}
you can then define...
#define THROW_HELPER(ex_type) \
for (std::stringstream ss; true; throwError<ex_type>(__FILE__, __func__, __LINE__, ss.str())) \
ss
#define INVALID_ARGUMENT_ERROR THROW_HELPER(std::invalid_argument)
#define LOGIC_ERROR THROW_HELPER(std::logic_error)
These can then be used as, e.g...
LOGIC_ERROR << "extra messages go here";
Note that currently two separate std::stringstream instances are created in the process of throwing an exception so the code shown should probably be 'compacted' a bit to prevent that [left as an exercise :-) ].
I propose a different option: libfmt!
#define LOGIC_ERROR(...) \
throwError<std::logic_error>(__FILE__, __func__, __LINE__, fmt::format(__VA_ARGS__))
Usage:
if (condition == bad)
LOGIC_ERROR("you did a bad because condition {} != {}", condition, bad);
The downside of this approach is that fmt::format will throw an exception if the format string is invalid. You could instead check it at compile-time using FMT_STRING() macro:
#define LOGIC_ERROR(string) \
throwError<std::logic_error>(__FILE__, __func__, __LINE__, string)
#define LOGIC_ERROR_P(string, ...) \
throwError<std::logic_error>(__FILE__, __func__, __LINE__, \
fmt::format(FMT_STRING(string), __VA_ARGS__))
Here I've created two versions of LOGIC_ERROR with and without extra parameters. It possible to have a single a single macro dispatch between those two depending on the number of arguments, but that's left as an exercise to the reader.
I'm trying to use a macro to queue up a single log line locally in an ostringstream and then dump the entire contents of that ostringstream when the line is over. I want to still use stream insert syntax, however. So I want to turn a log line like this:
std::cerr << "Some error in my function. Code is " << errCode << " exiting" << std::endl;
...into this
SERR("Some error in my function. Code is " << errCode << " exiting);
I've got something simple that works well. That is, until I put it in an if-else statement. Obviously my macro is bad but I am at a loss as to what to do.
Here is a small sample program, hacked up to illustrate the problem.:
#include <iostream>
#include <sstream>
#define SERR(x) { std::ostringstream _s; ; _s << x << std::endl; std::cerr << _s.str(); }
int main()
{
std::cout << "Hello World!\n";
bool val = false;
if (val)
SERR("No error");
else
SERR("Error");
}
The error message I get from the compiler in this sample is:
1>c:\users\joe\source\repos\consoleapplication5\consoleapplication5\consoleapplication5.cpp(15):
error C2181: illegal else without matching if
Any ideas what I've got wrong here?
(Note I'm not in a place where I can use a 3rd Party logging solution now so it's got to be something simple like this. I could just leave all this as normal std::cerr/std::cout/std::clog messages, if I had to but I'd prefer something simple to minimize the chances of interleaving of log messages from my multithreaded app.)
Just try to expand it and see what you get:
#include <iostream>
#include <sstream>
int main()
{
std::cout << "Hello World!\n";
bool val = false;
if (val)
{ std::ostringstream _s; ; _s << "No error" << std::endl; std::cerr << _s.str(); };
else
{ std::ostringstream _s; ; _s << "Error" << std::endl; std::cerr << _s.str(); };
}
Notice how { } block is terminated with ;?
If you need a macro, you should always write it using do { } while (0) like this:
#define SERR(x) \
do { \
std::ostringstream _s; \
_s << (x) << std::endl; \
std::cerr << _s.str(); \
} while (0)
Not only this solves your issue, but also make it mandatory to add ; after the macro. Otherwise people could use it two ways:
SERR("foo") // without ;
...
SERR("bar"); // with ;
When I test a method using
BOOST_CHECK_NO_THROW( method_to_test() );
and an exception is thrown, it displays that an exception was thrown, but never the exception's message like this:
test.cpp(14): error in "test": incorrect exception my_exception is caught
Is it possible to print the exception message as well, i.e. the string returned by my_exception.what()? my_exception is derived from std::exception and overloads what().
I found myself annoyed by the same problem with BOOST_REQUIRE_NO_THROW. I solved it by simply removing the BOOST_REQUIRE_NO_THROW. This results in output like:
unknown location(0): fatal error in "TestName": std::runtime_error: Exception message
and aborts the test (but goes on with the next text), which is what I wanted. This doesn't help much if you wanted to use BOOST_CHECK_NO_THROW or BOOST_WARN_NO_THROW, though.
I read a bit in the boost headers and redefined BOOST_CHECK_NO_THROW_IMPL in my own header file I use in the project to redefine the boost behavior. Now it looks like this:
#ifndef _CATCH_BOOST_NO_THROW_H_
#define _CATCH_BOOST_NO_THROW_H_
#include <boost/test/unit_test.hpp>
#include <sstream>
#include <string>
#define BOOST_CHECK_NO_THROW_IMPL( S, TL ) \
try { \
S; \
BOOST_CHECK_IMPL( true, "no exceptions thrown by " BOOST_STRINGIZE( S ), TL, CHECK_MSG ); } \
catch( const std::exception & e ) { \
std::stringstream ss; \
ss << std::endl \
<< "-----------------------------------------------" << std::endl \
<< "test case: " << boost::unit_test::framework::current_test_case().p_name << std::endl \
<< std::endl << "exception message: " << e.what() << std::endl; \
BOOST_TEST_MESSAGE(ss.str()); \
BOOST_CHECK_IMPL( false, "exception thrown by " BOOST_STRINGIZE( S ), TL, CHECK_MSG ); \
} \
catch( ... ) { \
std::stringstream ss; \
ss << std::endl \
<< "-----------------------------------------------" << std::endl \
<< "test case: " << boost::unit_test::framework::current_test_case().p_name << std::endl \
<< std::endl << "exception message : <unknown exception>" << std::endl; \
BOOST_TEST_MESSAGE(ss.str()); \
BOOST_CHECK_IMPL( false, "exception thrown by " BOOST_STRINGIZE( S ), TL, CHECK_MSG ); \
} \
/**/
#define BOOST_WARN_NO_THROW( S ) BOOST_CHECK_NO_THROW_IMPL( S, WARN )
#define BOOST_CHECK_NO_THROW( S ) BOOST_CHECK_NO_THROW_IMPL( S, CHECK )
#define BOOST_REQUIRE_NO_THROW( S ) BOOST_CHECK_NO_THROW_IMPL( S, REQUIRE )
#endif // _CATCH_BOOST_NO_THROW_H_
The disadvantages are: It works as long as there are no changes in BOOST_*_NO_THROW
and
the exception message will be printed before it is marked as error in the test output. That looks in the first place a bit pitty, that's why I group the output by writing "---" to the outstream to enhance the reading. But code after BOOST_CHECK_IMPL will never be reached.
The solution above work quite nice for me. Feel free to use to, if you got the same whish =)
(Using CDash for ctest output, don't forget to increase the test output limit, or simple disable the limit: http://web.archiveorange.com/archive/v/5y7PkVuHtkmVcf7jiWol )
Solution 1.
Use a wrapper method that catches the exception, then prints the error message and then re-throws so that BOOST can report it:
void method_to_test(int s)
{
if(s==0)
throw std::runtime_error("My error message");
}
void middle_man(int x)
{
try
{
method_to_test(x);
}catch(std::exception& e)
{
std::stringstream mes;
mes << "Exception thrown: " << e.what();
BOOST_TEST_MESSAGE(mes.str());// BOOST_ERROR(mes.str());
throw;
}
}
Then your test case would read:
BOOST_AUTO_TEST_CASE(case1)
{
BOOST_CHECK_NO_THROW( middle_man(0) );
}
A drawback of this approach is that you will need to use a different middle_man function for every method_to_test.
Solution 2.
Use decorators, see this answer,
to do just what a wrapper from the previous solution would do.
template <class> struct Decorator;
template<class R,class ... Args>
struct Decorator<R(Args ...)>
{
std::function<R(Args ...)> f_;
Decorator(std::function<R(Args ...)> f):
f_{f}
{}
R operator()(Args ... args)
{
try
{
f_(args...);
}catch(std::exception& e)
{
std::stringstream mes;
mes << "Exception thrown: " << e.what();
BOOST_TEST_MESSAGE(mes.str());
throw;
}
}
};
template<class R,class ... Args>
Decorator<R(Args...)> makeDecorator(R (*f)(Args ...))
{
return Decorator<R(Args...)>(std::function<R(Args...)>(f));
}
then your test cases would look like this:
BOOST_AUTO_TEST_CASE(case2)
{
BOOST_CHECK_NO_THROW( makeDecorator(method_to_test)(0) );
BOOST_CHECK_NO_THROW( makeDecorator(another_method_to_test)() );
}
Is there easily embeddable C++ test lib with a friendly license? I would like a single header file. No .cpp files, no five petabytes of includes. So CppUnit and Boost.Test are out.
Basically all I want is to drop single file to project tree, include it and be able to write
testEqual(a,b)
and see if it fail. I'd use assert, but it doesn't work in non-debug mode and can't print values of a and b, and before rewriting assert I'd rather search existing library.
I'm tempted to say "write your own", which is what I have done. On the other hand, you might want to reuse what I wrote: test_util.hpp and test_util.cpp. It is straightforward to inline the one definition from the cpp file into the hpp file. MIT lisence. I have also pasted it into this answer, below.
This lets you write a test file like this:
#include "test_util.hpp"
bool test_one() {
bool ok = true;
CHECK_EQUAL(1, 1);
return ok;
}
int main() {
bool ok = true;
ok &= test_one();
// Alternatively, if you want better error reporting:
ok &= EXEC(test_one);
// ...
return ok ? 0 : 1;
}
Browse around in the tests directory for more inspiration.
// By Magnus Hoff, from http://stackoverflow.com/a/9964394
#ifndef TEST_UTIL_HPP
#define TEST_UTIL_HPP
#include <iostream>
// The error messages are formatted like GCC's error messages, to allow an IDE
// to pick them up as error messages.
#define REPORT(msg) \
std::cerr << __FILE__ << ':' << __LINE__ << ": error: " msg << std::endl;
#define CHECK_EQUAL(a, b) \
if ((a) != (b)) { \
REPORT( \
"Failed test: " #a " == " #b " " \
"(" << (a) << " != " << (b) << ')' \
) \
ok = false; \
}
static bool execute(bool(*f)(), const char* f_name) {
bool result = f();
if (!result) {
std::cerr << "Test failed: " << f_name << std::endl;
}
return result;
}
#define EXEC(f) execute(f, #f)
#endif // TEST_UTIL_HPP
Try google-test https://github.com/google/googletest/
it's really light weight, cross platform and simple.
Is there a way to define/undefine debug messages using std::cout whenever inside a program?
I am aware that there are such things such as #define, #ifndef, but I was thinking is there a cleaner way to having a variable say:
# debug ON
That prints all of my debug data (using std::cout). Consequently, we'll have code like this for debug:
#ifndef DEBUG
// do something useful
#endif
I find the above code cumbersome when you write 100s of debug code.
Thanks!
Carlo
#ifdef DEBUG
#define DEBUG_MSG(str) do { std::cout << str << std::endl; } while( false )
#else
#define DEBUG_MSG(str) do { } while ( false )
#endif
int main()
{
DEBUG_MSG("Hello" << ' ' << "World!" << 1 );
return 0;
}
Some logging libraries are pretty heavy weight unless you have complex logging needs. Here's something I just knocked together. Needs a little testing but might meet your requirements:
#include <cstdio>
#include <cstdarg>
class CLog
{
public:
enum { All=0, Debug, Info, Warning, Error, Fatal, None };
static void Write(int nLevel, const char *szFormat, ...);
static void SetLevel(int nLevel);
protected:
static void CheckInit();
static void Init();
private:
CLog();
static bool m_bInitialised;
static int m_nLevel;
};
bool CLog::m_bInitialised;
int CLog::m_nLevel;
void CLog::Write(int nLevel, const char *szFormat, ...)
{
CheckInit();
if (nLevel >= m_nLevel)
{
va_list args;
va_start(args, szFormat);
vprintf(szFormat, args);
va_end(args);
}
}
void CLog::SetLevel(int nLevel)
{
m_nLevel = nLevel;
m_bInitialised = true;
}
void CLog::CheckInit()
{
if (!m_bInitialised)
{
Init();
}
}
void CLog::Init()
{
int nDfltLevel(CLog::All);
// Retrieve your level from an environment variable,
// registry entry or wherecer
SetLevel(nDfltLevel);
}
int main()
{
CLog::Write(CLog::Debug, "testing 1 2 3");
return 0;
}
Probably not. I would recommend using a logging library. I'm not sure what the best option is for C++ anymore, but I've used log4cpp in the past and found it pretty good.
EDIT: I assume on the fly means # runtime. If you just need it to be a compile time flag, then Gianni's answer is probably easiest to implement. Logging libraries give you a lot of flexibility and allow reconfiguration # runtime though.
Another simple solution, involves opening a std::ostream reference to cout in debug mode, and /dev/null in non-debug mode, like so:
In debug.h:
extern std::ostream &dout;
In debug.c
#ifdef DEBUG
std::ostream &dout = cout;
#else
std::ofstream dev_null("/dev/null");
std::ostream &dout = dev_null;
#endif
And then:
dout << "This is a debugging message";
Of course, this would only work on any system where /dev/null points to a null device. Since the dout reference is global here, it would much like cout. In this way, you can point the same stream to multiple output streams, for example to a log file, depending of the value of debug flags, etc.
Although the question is old, and there are some good answers, i want to post also a solution to this. It is like Giannis approach but different. And also, i used std::cerr instead of std::cout, but you can change this really quick.
#include <iostream>
#ifdef DEBUG
# define DEBUG_LOG std::cerr
#else
class log_disabled_output {};
static log_disabled_output log_disabled_output_instance;
template<typename T>
log_disabled_output& operator << (log_disabled_output& any, T const& thing) { return any; }
// std::endl simple, quick and dirty
log_disabled_output& operator << (log_disabled_output& any, std::ostream&(*)(std::ostream&)) { return any; }
# define DEBUG_LOG log_disabled_output_instance
#endif
int main() {
int x=0x12345678;
DEBUG_LOG << "my message " << x << " " << "\n more information" << std::endl;
};
Now you can use it just like a output stream.
(Note: iostream is only included if cerr is used. This will reduce the amount of inclusion if you don't have it already included. -edit: not with std::endl support).
If DEBUG is defined cerr is used to print the error. Otherwise the dummy class log_disabled_output is instantiated statically and operator<< is overloaded to any type. The vantage is; If you disable the logging, a clever compiler will notice that there is nothing to do with the stream and optimize the entire "line" away, so you don't have any overhead if DEBUG is disabled.
I was trying to do the same thing. After some research, I developed the following, and it seems to work. Please comment if you see anything wrong.
ostream DbgMsg(NULL);
enum {
DBGMSG_NONE,
DBGMSG_DEFAULT,
DBGMSG_VERBOSE
} DbgLvl = DBGMSG_DEFAULT;
ostream &DbgMsgDefault(ostream &stream) {
return (DbgLvl>=DBGMSG_DEFAULT) ? cout : stream;
}
ostream &DbgMsgVerbose(ostream &stream) {
return (DbgLvl>=DBGMSG_VERBOSE) ? cout : stream;
}
void main() {
DbgMsg<<DbgMsgDefault<<"default:default"<<endl;
DbgMsg<<DbgMsgVerbose<<"default:verbose"<<endl;
DbgLvl = DBGMSG_NONE;
DbgMsg<<DbgMsgDefault<<"none:default"<<endl;
}
A clean thing to do would be to use cerr.
"cerr" acts essentially as "cout", but always flushes the output (useful for debugging, by the way). If you need to remove all the messages, you can comment out all the cerr messages with a simple find-and-replace (cerr into //cerr).
There are probably even better ways to use cerr and to desactivate it cleanly (which writes into a special stream, the error stream, hence the name).
I hope this helps.
This is what I used (worked with VC++) - here "##" is used for concatennation
#ifdef DEBUG
#define pout cout
#else
#define pout / ## / cout
#endif
For other compilers use this :
#ifdef DEBUG
#define pout cout
#else
#define pout 0 && cout
#endif
Usage :
pout << "hello world" << endl;
I was looking for similar example and sharing my example below:
#include <iostream>
enum debug_option
{
DEBUG_DISABLE,
DEBUG_ENABLE
};
class debug
{
public:
debug_option debug_state;
debug() : debug_state(DEBUG_ENABLE) {} // constr
debug(debug_option state) : debug_state(state) {} // constr
template<typename T>
debug & operator<< (T input)
{
if (this->debug_state == DEBUG_ENABLE)
std::cout << input;
return *this;
}
};
int main()
{
debug log, log_lev2(DEBUG_DISABLE);
log << "print 1..\n" << 55 << " over\n";
log.debug_state = DEBUG_DISABLE;
log << "print 2..\n" << 3 << "over\n";
log_lev2 << "print 3..\n" << 4 << "over\n";
log_lev2.debug_state = DEBUG_ENABLE;
log_lev2 << "print 5..\n";
std::cout << "std::cout << print..\n";
return 0;
}
Better suggestions are always welcome.