diff --git a/include/fmt/printf.h b/include/fmt/printf.h index e8caecaa..005df5f1 100644 --- a/include/fmt/printf.h +++ b/include/fmt/printf.h @@ -573,18 +573,41 @@ void printf(internal::basic_buffer &buf, basic_string_view format, } template -struct printf_context { +struct basic_printf_context_t { typedef basic_printf_context< std::back_insert_iterator, typename Buffer::value_type> type; }; -typedef basic_format_args::type> printf_args; -typedef basic_format_args::type> wprintf_args; +typedef basic_printf_context_t::type printf_context; +typedef basic_printf_context_t::type wprintf_context; + +typedef basic_format_args printf_args; +typedef basic_format_args wprintf_args; + +/** + \rst + Constructs an `~fmt::format_arg_store` object that contains references to + arguments and can be implicitly converted to `~fmt::printf_args`. + \endrst + */ +template +inline format_arg_store + make_printf_args(const Args &... args) { return {args...}; } + +/** + \rst + Constructs an `~fmt::format_arg_store` object that contains references to + arguments and can be implicitly converted to `~fmt::wprintf_args`. + \endrst + */ +template +inline format_arg_store + make_wprintf_args(const Args &... args) { return {args...}; } template inline std::basic_string vsprintf(const S &format, - basic_format_args>::type> args) { basic_memory_buffer buffer; printf(buffer, to_string_view(format), args); @@ -605,7 +628,7 @@ inline FMT_ENABLE_IF_STRING(S, std::basic_string) sprintf(const S &format, const Args & ... args) { internal::check_format_string(format); typedef internal::basic_buffer buffer; - typedef typename printf_context::type context; + typedef typename basic_printf_context_t::type context; format_arg_store as{ args... }; return vsprintf(to_string_view(format), basic_format_args(as)); @@ -613,7 +636,7 @@ inline FMT_ENABLE_IF_STRING(S, std::basic_string) template inline int vfprintf(std::FILE *f, const S &format, - basic_format_args>::type> args) { basic_memory_buffer buffer; printf(buffer, to_string_view(format), args); @@ -636,7 +659,7 @@ inline FMT_ENABLE_IF_STRING(S, int) fprintf(std::FILE *f, const S &format, const Args & ... args) { internal::check_format_string(format); typedef internal::basic_buffer buffer; - typedef typename printf_context::type context; + typedef typename basic_printf_context_t::type context; format_arg_store as{ args... }; return vfprintf(f, to_string_view(format), basic_format_args(as)); @@ -644,7 +667,7 @@ inline FMT_ENABLE_IF_STRING(S, int) template inline int vprintf(const S &format, - basic_format_args>::type> args) { return vfprintf(stdout, to_string_view(format), args); } @@ -663,7 +686,7 @@ inline FMT_ENABLE_IF_STRING(S, int) printf(const S &format_str, const Args & ... args) { internal::check_format_string(format_str); typedef internal::basic_buffer buffer; - typedef typename printf_context::type context; + typedef typename basic_printf_context_t::type context; format_arg_store as{ args... }; return vprintf(to_string_view(format_str), basic_format_args(as)); @@ -672,7 +695,7 @@ inline FMT_ENABLE_IF_STRING(S, int) template inline int vfprintf(std::basic_ostream &os, const S &format, - basic_format_args>::type> args) { basic_memory_buffer buffer; printf(buffer, to_string_view(format), args); @@ -695,7 +718,7 @@ inline FMT_ENABLE_IF_STRING(S, int) const S &format_str, const Args & ... args) { internal::check_format_string(format_str); typedef internal::basic_buffer buffer; - typedef typename printf_context::type context; + typedef typename basic_printf_context_t::type context; format_arg_store as{ args... }; return vfprintf(os, to_string_view(format_str), basic_format_args(as)); diff --git a/test/printf-test.cc b/test/printf-test.cc index d3e222f2..f40c302f 100644 --- a/test/printf-test.cc +++ b/test/printf-test.cc @@ -501,9 +501,8 @@ TEST(PrintfTest, OStream) { } TEST(PrintfTest, VPrintf) { - typedef fmt::printf_context::type context; - fmt::format_arg_store as{42}; - fmt::basic_format_args args(as); + fmt::format_arg_store as{42}; + fmt::basic_format_args args(as); EXPECT_EQ(fmt::vsprintf("%d", args), "42"); EXPECT_WRITE(stdout, fmt::vprintf("%d", args), "42"); EXPECT_WRITE(stdout, fmt::vfprintf(stdout, "%d", args), "42"); @@ -518,3 +517,42 @@ void check_format_string_regression(fmt::string_view s, const Args&... args) { TEST(PrintfTest, CheckFormatStringRegression) { check_format_string_regression("%c%s", 'x', ""); } + +TEST(PrintfTest, VSPrintfMakeArgsExample) { + fmt::format_arg_store as{ + 42, "something"}; + fmt::basic_format_args args(as); + EXPECT_EQ( + "[42] something happened", fmt::vsprintf("[%d] %s happened", args)); + auto as2 = fmt::make_printf_args(42, "something"); + fmt::basic_format_args args2(as2); + EXPECT_EQ( + "[42] something happened", fmt::vsprintf("[%d] %s happened", args2)); + //the older gcc versions can't cast the return value +#if !defined(__GNUC__) || (__GNUC__ > 4) + EXPECT_EQ( + "[42] something happened", + fmt::vsprintf( + "[%d] %s happened", fmt::make_printf_args(42, "something"))); +#endif +} + +TEST(PrintfTest, VSPrintfMakeWArgsExample) { + fmt::format_arg_store as{ + 42, L"something"}; + fmt::basic_format_args args(as); + EXPECT_EQ( + L"[42] something happened", + fmt::vsprintf(L"[%d] %s happened", args)); + auto as2 = fmt::make_wprintf_args(42, L"something"); + fmt::basic_format_args args2(as2); + EXPECT_EQ( + L"[42] something happened", fmt::vsprintf(L"[%d] %s happened", args2)); + // the older gcc versions can't cast the return value +#if !defined(__GNUC__) || (__GNUC__ > 4) + EXPECT_EQ( + L"[42] something happened", + fmt::vsprintf( + L"[%d] %s happened", fmt::make_wprintf_args(42, L"something"))); +#endif +}