Search code examples
c++stringvariadic-macros

Convert __VA_ARGS__ to string


I'm trying to redefine a Variadic Macro to use cout instead of printf. Here's the original code:

#define LOGE(...) PRINT_LEVEL(1, __VA_ARGS__);

  #define PRINT_LEVEL(level,...) do { \
      if (debug_components.DEBUG_COMPONENT >= level) \
          { printf("[%s]: ", levels_strings[level-1]); printf(__VA_ARGS__); printf("\n"); } \
    }while(0)

I converted this to the following to use cout instead of printf:

  #define PRINT_LEVEL(level,...) do { \
if (debug_components.DEBUG_COMPONENT >= level) \
{ std::string argString; sprintf(argString, __VA_ARGS__); std::cout << "[" << levels_strings[level-1] << "]" << argString << "\n";} \
    }while(0)

For some reason, __VA_ARGS__ works fine with printf, but NOT sprintf. It also does not work with cout. I'd like to know the correct way to convert __VA_ARGS__ to a string, or failing that, the correct way to just print it out using cout.


Solution

  • sprintf takes an extra argument, the data buffer to write the output to. You can't swap out printf for sprintf without making the changes to provide that buffer. It also doesn't return a pointer to the string, so you can't assign the result to a std::string and expect it to work. If you're operating unsafely (assuming a maximum buffer length), something as simple as:

    #define PRINT_LEVEL(level,...) do { \
        if (debug_components.DEBUG_COMPONENT >= level) \
        { 
            char buf[1024];
            sprintf(buf, __VA_ARGS__); std::cout << "[" << levels_strings[level-1] << "]" << buf << "\n";} \
    }while(0)
    

    would work (and with truncation, could be done with safety if not reliably via snprintf), but if you're using C++ types anyway, you might want to look at a non-printf-y solution