C++ macro function expansion based on the macro function arguments - c++

Some systems I use don't have a logging library I'm using, which is OK for well-tested code on production runs --- the logging library is mostly for debugging and testing. On my main development machine, and on a couple of servers I frequently run experiments on, the logging library exists. But occasionally I need to farm out experiments to another server with many more nodes and cores but that does not have the logging library.
The library (Google glog) provides, for example, the following macro functions:
LOG(INFO) << "Insert my message here.";
LOG(FATAL) << "Insert another message here.";
So, what I've done is defined the following:
#ifdef NOLOGGING
#define MYLOG(i,m) std::cerr << #i << ": " << m << "\n";
#else
#define MYLOG(i,m) LOG(i) << m ;
#endif
Using those definitions, I can now write statements like this:
MYLOG(INFO, "My info message");
MYLOG(FATAL,"My fatal message");
If compiled with flag -DNOLOGGING, the last two statements will be expanded to:
std::cerr << "INFO" << ": " << "My info message" << "\n";
std::cerr << "FATAL" << ": " << "My fatal message" << "\n";
Wherease, if the -DNOLOGGING flag is not used in compilation, they will be expanded to:
LOG(INFO) << "My info message";
LOG(FATAL) << "My fatal message";
The solution I've described above is satisfactory, but not ideal.
Ideally, when I don't have acces to the logging library, statements like MYLOG(FATAL,"foo") would expand to statements that print to std::cerr; however, statments like MYLOG(INFO,"bar") would expand to nothing. In other words, when I can't use the logging library, I want statements like MYLOG(INFO,"bar") to be ignored. The idea is that I don't care too much about log messages of the INFO severity when I'm using the servers without the logging library, but I do still want to see messages of the FATAL severity.
How, if possible, can I do this using only preprocessor directives?

I don't think you can do it solely with preprocessing directives, since the preprocessor doesn't really give you the necessary mechanisms to guide macro expansion based on the arguments to the macro.
That said, you can perpetrate some mildly ugly hacks that will work. Consider the following code:
#include <iostream>
#define MYLOG_ERR 1
#define MYLOG_INFO 0
#define P(a,b) a##b
#define MYLOG(x,y) do { if (P(MYLOG_,x)) { std::cerr << y << std::endl; } } while (0)
int main(void)
{
MYLOG(ERR, "err");
MYLOG(INFO, "info");
}
This approach relies on the compiler's optimizer to recognize some common idioms, such as do { ... } while (0) and if (0) / if (1) to optimize away compile-time known conditions. But, I think it'll give you what you want.

Related

errno doesn't change after putting a negative value in sqrt()

With errno, I am trying to check if cmath functions produce a valid result. But even after I put a negative value in sqrt() or log(), errno stays at value 0.
Can anyone know why, and how I can make errno behave correctly?
The environment is macOS Monterey version 12.6.1, the compiler is gcc version 11.3.0 (Homebrew GCC 11.3.0_1) or Apple clang version 14.0.0 (clang-1400.0.29.202) (I tried the 2 compilers).
The compile command is g++ test_errno.cpp -o test_errno -std=c++14.
The piece of code I tried is directly copied from this page. The following is the code.
#include <iostream>
#include <cmath>
#include <cerrno>
#include <cstring>
#include <clocale>
int main()
{
double not_a_number = std::log(-1.0);
std::cout << not_a_number << '\n';
if (errno == EDOM) {
std::cout << "log(-1) failed: " << std::strerror(errno) << '\n';
std::setlocale(LC_MESSAGES, "de_DE.utf8");
std::cout << "Or, in German, " << std::strerror(errno) << '\n';
}
}
Its result didn't print the error messages, which should be printed if errno is set correctly.
It seems that on macOS, errno is not used, from this bug report from #GAVD's comment.
I could check that via math_errhandling value from #Pete Becker's comment.
It seems there are 2 ways of math error handling in C/C++, either with errno, or with floating-point exception, as the 2nd link above shows.
We can check which way (or both of them) the system's math library employs, via checking if macro constant math_errhandling is equal to MATH_ERREXCEPT or MATH_ERRNO, like the following (copied from the 2nd link):
std::cout << "MATH_ERRNO is "
<< (math_errhandling & MATH_ERRNO ? "set" : "not set") << '\n'
<< "MATH_ERREXCEPT is "
<< (math_errhandling & MATH_ERREXCEPT ? "set" : "not set") << '\n';
And on my system, the output is
MATH_ERRNO is not set
MATH_ERREXCEPT is set
, which means the system does not use errno for reporting math errors, but use floating-point exception.
That's why errno stays at value 0 no matter what, and I should have used std::fetestexcept() to check error conditions.
With floating-point exceptions, std::feclearexcept(FE_ALL_EXCEPT); corresponds to errno = 0;, and std::fetestexcept(FE_DIVBYZERO) corresponds to errno == ERANGE for example.
I'm going to take a stab in the dark and guess you are enabling fast-math in your build?
Without fast-math:
https://godbolt.org/z/vMo1P7Mn1
With fast-math:
https://godbolt.org/z/jEsGz7n38
The error handling within cmath tends to break things like vectorisation & constexpr (setting external global variables, is a side effect that breaks both cases). As a result, you are usually better off checking for domain errors yourself...

How to disable std::clog logging from source code?

When developing code, I have many console logging (std::clog) and some console output (std::cout). But now, I wanted to do online submission of my source code and I want to disable all the console logging (clog) but keep the console output (cout)
I can surely comment all of my //std::clog, but is there a better way to disable all logging inside my source file,?
You can redirect clog, create your own ofstream and use rdbuf function.
std::ofstream nullstream;
std::clog.rdbuf(nullstream.rdbuf());
Copied from Andreas Papadopoulos' answer to a slightly different question -- be sure to upvote him there!
Sure, you can (example here):
int main() {
std::clog << "First message" << std::endl;
std::clog.setstate(std::ios_base::failbit);
std::clog << "Second message" << std::endl;
std::clog.clear();
std::clog << "Last message" << std::endl;
return 0;
}
Outputs:
First message
Last message
This is because putting the stream in fail state will make it silently discard any output, until the failbit is cleared.

C++ VS Debug code, set your own debug flags

I wonder if there is way to define your own debug flags in VS for C++.
For example the code below is only executed in debug mode. I want to have another piece of code that maybe prints "Hello World"that only prints at debug level 2. How do you define a level 2 debug flag in VS? is it via properties?
#ifdef _DEBUG
std::cout << "Hello" << std::endl;
#endif
You use your own macros.
#ifdef DEBUG_LEVEL_2
std::cout << "Hello" << std::endl;
#endif
or
#if defined (DEBUG_LEVEL) && DEBUG_LEVEL >= 2
std::cout << "Hello" << std::endl;
#endif
and then you either
#define DEBUG_LEVEL_2
or
#define DEBUG_LEVEL 2
manually, or define it in the "Preprocessor" tab in the project settings, or pass it to the compiler using the /Dflag if you're compiling on the command line.

How to disable cout output in the runtime?

I often use cout for debugging purpose in many different places in my code, and then I get frustrated and comment all of them manually.
Is there a way to suppress cout output in the runtime?
And more importantly, let's say I want to suppress all cout outputs, but I still want to see 1 specific output (let's say the final output of the program) in the terminal.
Is it possible to use an ""other way"" of printing to the terminal for showing the program output, and then when suppressing cout still see things that are printed using this ""other way""?
Sure, you can (example here):
int main() {
std::cout << "First message" << std::endl;
std::cout.setstate(std::ios_base::failbit);
std::cout << "Second message" << std::endl;
std::cout.clear();
std::cout << "Last message" << std::endl;
return 0;
}
Outputs:
First message
Last message
This is because putting the stream in fail state will make it silently discard any output, until the failbit is cleared.
To supress output, you can disconnect the underlying buffer from cout.
#include <iostream>
using namespace std;
int main(){
// get underlying buffer
streambuf* orig_buf = cout.rdbuf();
// set null
cout.rdbuf(NULL);
cout << "this will not be displayed." << endl;
// restore buffer
cout.rdbuf(orig_buf);
cout << "this will be dispalyed." << endl;
return 0;
}
Don't use cout for debugging purposes, but define a different object (or function, or macro) that calls through to it, then you can disable that function or macro in one single place.
You can user cerr - standard output stream for errors for your debug purposes.
Also, there is clog - standard output stream for logging.
Typically, they both behave like a cout.
Example:
cerr << 74 << endl;
Details: http://www.cplusplus.com/reference/iostream/cerr/
http://www.cplusplus.com/reference/iostream/clog/
If you include files which involve cout you may want to write the code at the start (outside of main), which can be done like this:
struct Clearer {
Clearer() { std::cout.setstate(std::ios::failbit); }
} output_clearer;
It seems you print debug messages. You could use TRACE within Visual C++/MFC or you just might want to create a Debug() function which takes care of it. You can implement it to turn on only if a distinct flag is set. A lot of programs use a command line parameter called verbose or -v for instance, to control the behavior of their log and debug messages.

Shall I use cerr

Is it in good style do use cerr in situation described below?
try
{
cout << a + b;
}
catch(const IntException& e)
{
cerr << "Exception caught: " << typeid(e).name(); //using cerr not cout
}
catch(...)
{
cerr << "Unknown exception.";//using cerr not cout
}
or cout should be used? See comments in code.
stderr is the traditional stream to send error messages (so that the OS/shell/whatever can capture error messages separately from "normal" output), so yes, use std::cerr!
I make no comment as to whether catching an exception simply to print it out is any better than simply letting the exception propagating out of your application...
Yes, because while by default they both go to the terminal, you could change where their output is directed, and you may wish cerr to go to a log file while cout continues to just go to stdout.
Essentially it gives you more control over where different output goes if you want it now or in the future.
Sure, it's good to use cerr there. You can redirect cerr differently from cout, sometimes that helps you to highlight problems that could go buried in a huge cout log file.
One detail to keep in mind is that sending output directly to the terminal (with either cout or cerr), you do limit your ability to test for your error messages. It's always worth posing the question "How do I unit test this?".