Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 215
Tony Tony Avatar asked Aug 11 '17 07:08

Tony Tony


People also ask

Can you concatenate C style strings?

You can concatenate two C-style strings in C++ using strcat() function.

Which function is used for string concatenation in C?

(String Concatenation) In the C Programming Language, the strcat function appends a copy of the string pointed to by s2 to the end of the string pointed to by s1. It returns a pointer to s1 where the resulting concatenated string resides.

What is the difference between string concatenation and interpolation?

You can think of string concatenation as gluing strings together. And, you can think of string interpolation without strings as injecting strings inside of other strings.

What is the difference between strcat and Strncat?

This example demonstrates the difference between strcat() and strncat() . The strcat() function appends the entire second string to the first, whereas strncat() appends only the specified number of characters in the second string to the first.


2 Answers

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);
like image 95
Caleth Avatar answered Oct 13 '22 00:10

Caleth


I suggest adding an operator<<() to the class

class Logger
{
     public:

          Logger &operator<<(const std::string &s)
          {
              logging(s)
              return *this;
          };

          Logger &operator<<(const char *s)
          {
              return operator<<(std::string(s));
          }


          template <class T>
               Logger &operator<<(const T &v)
          {
               std::ostringstream s;
               s << v;
               return operator<<(logging(ss.str()));
          };

       // other stuff you have in your class, including the logging() function
};

//  to use

logMe << "log this msg" << a << b;

Not quite the same syntax to use this as you have described, but it works more generally.

like image 32
Peter Avatar answered Oct 13 '22 00:10

Peter