Append to ostream in a preprocessor macro

Patrizio Bertoni :

I'd mimick the widespread BOOST_LOG_TRIVIAL with a custom define which uses std::cout instead.

// Building with
// g++ -std=c++14 -Wall -pedantic -g -O0 -DBOOST_LOG_DYN_LINK -c log.cpp
// g++ log.o -lpthread -lboost_log -lboost_log_setup  -lboost_system -lboost_thread -o bl

#define FORBID_BOOST_LOG
#define VALUE_TO_STRING(x) #x

#ifdef FORBID_BOOST_LOG
    #include <iostream>
    #define LOG(sev) std::cout << "[" << VALUE_TO_STRING(sev) << "]  "
#else
    #include <boost/log/trivial.hpp>
    #define LOG(sev) BOOST_LOG_TRIVIAL(sev)
#endif

int main()
{
    LOG(info) << "hello logging";
}

Which is nice, but the only feature missing here it that nice trailing newline char added by boost trivial logging.

I've read across few boost headers, but actually have no idea about the correct preprocessor syntax to mantain hundreds of LOG(sev) calls agnostic about the preprocessor selected implementation.

Alan Birtles :

One solution is to create a logging object that prints a newline on destruction. The object will be destructed at the end of the logging expression so you'll get a new line at the end of your log message (this is probably how boost log works too):

#include <iostream>
struct Log
{
    Log(const char* sev)
    {
        std::cout << "[" << VALUE_TO_STRING(sev) << "]  ";
    }
    ~Log()
    {
        std::cout << "\n";
    }

    template < typename T >
    Log& operator <<(const T& value)
    {
        std::cout << value;
        return *this;
    }
};
#define LOG(sev) Log(VALUE_TO_STRING(sev))

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=220715&siteId=1