c++stringlog4cpp

c++ concatenate different types into a string for function


I have different parts of my application calling a logger function to log details.

Logger class

std::string filename = "blahblah"; // variable to store the location of the properties file 
log4cpp::PropertyConfigurator::configure(filename);

void Logger::logging(const std::string& msg)
{
   Log4cpp::Category& myLogger = log4cpp::Category::getRoot();

   myLogger.log(log4cpp::Priority::INFO, msg);//only takes in string as input
}

Calling class

Logger logMe;

int a = 5;
double b = 6;

logMe.logging("log this msg" + a + "," + b);

I realised that the above will give me error, as a and b are of different types. One way to solve it is to use std::to_string

logMe.logging("log this msg" + std::to_string(a) + "," + std::to_string(b));

However, I have hundreds of calls to the logging function, and it will be time consuming to edit each and every call to std::to_string. Is/are there any easier way(s) to do it?

Oh and to clarify, the code works before as the previous way was by defining a #define function.

#Define logging(FLAG, X)\
do {\
    ...
    clog << x; \
}while(0)

logging(LogFlag::Warning, "log this msg" << a << "," << b << endl);

But i am now rewriting parts of the code to comply to static testing.

Thanks in advance.


Solution

  • You can add an overload of logging that takes a parameter pack and joins it up into a string, using std::stringstream

    In c++17, we can use a fold expression, e.g.

    template <typename Args ...>
    void Logger::logging(Args ... args)
    {
       std::stringstream ss;
       (ss << ... << args); 
    
       Log4cpp::Category& myLogger = log4cpp::Category::getRoot();
    
       myLogger.log(log4cpp::Priority::INFO, ss.str());
    }
    

    In c++11 or 14, we have to be slightly more tricky

    template <typename ... Args >
    void Logger::logging(Args ... args)
    {
       std::stringstream ss;
       std::initializer_list<int> unused{ (ss << args, 0)... };
    
       Log4cpp::Category& myLogger = log4cpp::Category::getRoot();
    
       myLogger.log(log4cpp::Priority::INFO, ss.str());
    }
    

    Then you call either as e.g.

    logMe.logging("log this msg", a, ",", b);