typesafe な sprintf

boost::format を使えばいいんだけど、operator%がなんとなく嫌だったり、フォーマット不能な場合にデフォルトで例外投げるのが嫌だったりするので、そのへんを補正してsprintf感覚で使えるようにしたマクロ。引数10個まで行ける。

#include <boost/preprocessor.hpp>
#include <boost/format.hpp>
#include <boost/algorithm/string.hpp>

// arg0 % arg1 % arg2 ・・・と追加していくためのマクロ。
#define X_GENERATE_FORMAT(z,n,x) %arg##n

// 関数本体生成マクロ.
//      テンプレートパラメータ、
//      第2以降の引数、
//      フォーマットに % で追加していく部分
// の3箇所がさらにマクロを呼ぶ。
#define X_GENERATE_FORMAT_FUNCTION(z,n,d)                                                       \
    template< BOOST_PP_ENUM_PARAMS(n,typename T)>                                               \
    inline std::string _fmt( const char* format, BOOST_PP_ENUM_BINARY_PARAMS(n,const T,& arg) ) \
    {                                                                                           \
        boost::format f;                                                                        \
        f.exceptions( boost::io::no_error_bits );                                               \
        f.parse(format);                                                                        \
        f BOOST_PP_REPEAT(n,X_GENERATE_FORMAT,_);                                               \
        return f.str();                                                                         \
    }

#define X_GENERATE_FORMAT_FUNCTION_ST(z,n,d)                                                    \
    template< BOOST_PP_ENUM_PARAMS(n,typename T)>                                               \
    inline std::string _fmt(                                                                    \
        const std::string& format,                                                              \
        BOOST_PP_ENUM_BINARY_PARAMS(n,const T,& arg) )                                          \
    {                                                                                           \
        return _fmt( format.c_str(), BOOST_PP_ENUM_PARAMS(n, arg));                             \
    }

#define X_GENERATE_FORMAT_FUNCTION_W(z,n,d)                                                         \
    template< BOOST_PP_ENUM_PARAMS(n,typename T)>                                                   \
    inline std::wstring _fmt( const wchar_t* format, BOOST_PP_ENUM_BINARY_PARAMS(n,const T,& arg) ) \
    {                                                                                               \
        boost::wformat f;                                                                           \
        f.exceptions( boost::io::no_error_bits );                                                   \
        f.parse(format);                                                                            \
        f BOOST_PP_REPEAT(n,X_GENERATE_FORMAT,_);                                                   \
        return f.str();                                                                             \
    }

#define X_GENERATE_FORMAT_FUNCTION_W_ST(z,n,d)                                                  \
    template< BOOST_PP_ENUM_PARAMS(n,typename T)>                                               \
    inline std::wstring _fmt(                                                                   \
        const std::wstring& format,                                                             \
        BOOST_PP_ENUM_BINARY_PARAMS(n,const T,& arg) )                                          \
    {                                                                                           \
        return _fmt( format.c_str(), BOOST_PP_ENUM_PARAMS(n, arg));                             \
    }

// 単一引数オーバーロード
inline std::string _fmt( const char* format ){ return std::string( format ); }
inline std::string _fmt( const std::string& format ){ return format; }
inline std::wstring _fmt( const wchar_t * format ){ return std::wstring( format ); }
inline std::wstring _fmt( const std::wstring& format ){ return format; }


// 関数本体生成マクロを繰り返し呼び出す。 
BOOST_PP_REPEAT_FROM_TO( 1, 10, X_GENERATE_FORMAT_FUNCTION, _)
BOOST_PP_REPEAT_FROM_TO( 1, 10, X_GENERATE_FORMAT_FUNCTION_ST, _ )
BOOST_PP_REPEAT_FROM_TO( 1, 10, X_GENERATE_FORMAT_FUNCTION_W, _)
BOOST_PP_REPEAT_FROM_TO( 1, 10, X_GENERATE_FORMAT_FUNCTION_W_ST, _)

#undef X_GENERATE_FORMAT_FUNCTION
#undef X_GENERATE_FORMAT_FUNCTION_ST
#undef X_GENERATE_FORMAT_FUNCTION_W
#undef X_GENERATE_FORMAT_FUNCTION_W_ST
#undef X_GENERATE_FORMAT