The easiest option would be to use an object that just swallows all the operator<<
calls (like @tkausl suggested in the comments):
godbolt example
#if SOMETHING
#define LOG std::cout
#else
struct nullout_t {};
template<class T>
constexpr nullout_t const& operator<<(nullout_t const& no, T&&) { return no; }
constexpr nullout_t nullout;
#define LOG nullout
#endif // SOMETHING
int main()
{
LOG << "hello world\n";
return 0;
}
Please note however this method completely relies on the compiler being able to eliminate the entire log statement.
So if your logging has any observable side-effects (or the compiler simply isn't able to prove it's dead code), you still will end up with some of the logging code running.
e.g. a simple string concatenation is already enough to prevent gcc from optimizing it out completely:
godbolt example
int main()
{
LOG << std::string("hello") + std::string("world\n");
return 0;
}
I wouldn't recommend using boost:iostreams
with null_sink
like @AndyG suggested, because that makes it very hard (if not impossible) for compilers to completely optimize out. (In the linked example you can see that main()
still actually calls operator<<
on the iostream) This is due to iostreams performing formatting first before actually passing the final result to the sink (null_sink
) - and formatting depends on the stream manipulators applied to the stream and the locale imbued into it - so the compiler would need to prove that nothing of that has any side effect for it to be able to optimize it out completely (which is rather hard).
If you want to be able to completely get rid of the entire logging code, you'd have to change your LOG
macro so that the preprocessor can completely remove the operator<<
calls as well, e.g.:
godbolt example
#include <iostream>
#if SOMETHING
#define LOG(...) std::cout __VA_ARGS__
#else
#define LOG(...)
#endif // SOMETHING
int main()
{
LOG(<< "hello world!\n");
LOG(<< "there are " << 5 << " cookies in the " << std::string("jar") << std::endl);
return 0;
}
By using the preprocessor to remove the code you can get rid of all logging logic, even if it would have observable side effects.