c++11variadic-macrosboost-preprocessorboost-formatgcc4.4

Feeding boost::format with variadic parameters


I am attempting to write a logging function which takes a variadic argument list and prints in a safe manor.
vprintf seems like the obvious answer, but I cannot seem to find a safe way to handle when the format string expects more arguments than were provided.

Additionally, it would be very nice if I could rearrange the order the parameters are printed.
This second requirement led me to boost::format, which seems to be exactly what I want, except that it does not accept a va_list for input.

I have done some extensive searching and the closest I could get was this solution:
boost::format with variadic template arguments

Unfortunately I am restricted to a specific gcc version which does not seem to include the std::initializer_list

In my searching, I have stumbled upon boost::preprocessor which seems like it should be able to accomplish what I want, but I am struggling with the implementation of it.

So, ideally, what I'm searching for is something that works as follows:

void loggerFunc(const char* msgFormat, ...){
    boost::format f(msgFormat);

    va_list args;
    va_start(args, msg);

    f & MagicalFunctionCall(args);

    va_end(args);
}

Where this MagicalFunctionCall(args) would convert my args, for example:
1, "Test", 3.4, "OtherString"
into something like:
1 & "Test" & 3.4 & "OtherString"

I'm not necessarily tied to boost::preprocessor or anything boost really, but it would be ideal to accomplish this without pulling in any additional 3rd party dependencies (we already use boost elsewhere in the project). I just suggested those libraries, because they seemed to be the most promising in accomplishing all of the above.

Thanks!


Solution

  • Instead of Boost Format you could use the fmt library which supports older compilers ({fmt} 4 supports gcc 4.4):

    void loggerFunc(const char *format, fmt::ArgList args) {
      std::string s = fmt::format(format, args);
      // log s
    }
    FMT_VARIADIC(void, loggerFunc, const char *)
    

    The loggerFunc generated by FMT_VARIADIC can be used with variable number of arguments:

    loggerFunc("{} {} {} {}", 1, "Test", 3.4, "OtherString");
    

    Disclaimer: I'm the author of the fmt library.