Paul C
Paul C

Reputation: 8497

Is there any way to use varargs with boost::format?

I'm kinda loathe to use a fixed-sized buffer and the vnsprintf usual suspects.

Would something like this work to have boost::format work with a variable argument list?

Sadly, I cannot use anything from C++11.

void formatIt(const char* msg, ...) {
        va_list args;
        va_start(args, msg);
        boost::format f(msg);
        for loop somehow {                  
          f % va_arg(args, const char *);   //does this work?           
        }
        va_end(args);
}

Upvotes: 6

Views: 1742

Answers (2)

Scott Langham
Scott Langham

Reputation: 60391

I used to use this:

inline static std::string FormatString()
{
    return std::string();
}

inline static std::string FormatString(const char* szMessage)
{
    return szMessage;
}

template<typename Type1>
static std::string FormatString(const char* formatString, const Type1& arg1)
{
    using namespace boost::io;
    boost::format formatter(formatString);
    formatter % arg1;
    return boost::str( formatter );
}

template<typename Type1, typename Type2>
static std::string FormatString(const char* formatString, const Type1& arg1, const Type2& arg2)
{
    using namespace boost::io;
    boost::format formatter(formatString);
    formatter % arg1 % arg2;
    return boost::str( formatter );
}

template<typename Type1, typename Type2, typename Type3>
static std::string FormatString(const char* formatString, const Type1& arg1, const Type2& arg2, const Type3& arg3)
{
    using namespace boost::io;
    boost::format formatter(formatString);
    formatter % arg1 % arg2 % arg3;
    return boost::str( formatter );
}

/// etc up to 10 args

I guess it doesn't use varargs as you requested, but do you often need to go above 10 or so arguments? There may be some macro magic that would make what you wanted happen, but err... that's magic, so you may be better off with just writing out all the versions.

Upvotes: 2

Scott Langham
Scott Langham

Reputation: 60391

I use this:

inline static std::string FormatStringRecurse(boost::format& message)
{
    return message.str();
}

template <typename TValue, typename... TArgs>
std::string FormatStringRecurse(boost::format& message, TValue&& arg, TArgs&&... args)
{
   message % std::forward<TValue>(arg);
   return FormatStringRecurse(message, std::forward<TArgs>(args)...);
}

template <typename... TArgs>
std::string FormatString(const char* fmt, TArgs&&... args)
{
    using namespace boost::io;
    boost::format message(fmt);
    return FormatStringRecurse(message, std::forward<TArgs>(args)...);
}

Upvotes: 8

Related Questions