From a63a24f2d7d9a425c20857e7089d54a3cf8789d2 Mon Sep 17 00:00:00 2001 From: Dean Moldovan Date: Sun, 27 Sep 2015 02:26:26 +0200 Subject: [PATCH 1/2] Add _format literal --- format.h | 38 ++++++++++++++++++++++++++++++++++++++ test/format-test.cc | 9 +++++++++ 2 files changed, 47 insertions(+) diff --git a/format.h b/format.h index 8260024f4877..b85ddcb15a65 100644 --- a/format.h +++ b/format.h @@ -177,6 +177,16 @@ inline uint32_t clzll(uint64_t x) { TypeName& operator=(const TypeName&) #endif +#ifndef FMT_USE_USER_DEFINED_LITERALS +// All compilers which support UDLs also support variadic templates. This +// makes the fmt::literals implementation easier. However, an explicit check +// for variadic templates is added here just in case. +# define FMT_USE_USER_DEFINED_LITERALS \ + FMT_USE_VARIADIC_TEMPLATES && \ + (FMT_HAS_FEATURE(cxx_user_literals) || \ + (FMT_GCC_VERSION >= 407 && FMT_HAS_GXX_CXX11) || _MSC_VER >= 1900) +#endif + #ifndef FMT_ASSERT # define FMT_ASSERT(condition, message) assert((condition) && message) #endif @@ -3005,6 +3015,34 @@ FMT_VARIADIC(int, printf, CStringRef) FMT_VARIADIC(int, fprintf, std::FILE *, CStringRef) } +#if FMT_USE_USER_DEFINED_LITERALS +namespace fmt { +namespace internal { + +template +struct UdlFormat { + const Char *str; + + template + auto operator()(Args && ... args) const + -> decltype(format(str, std::forward(args)...)) { + return format(str, std::forward(args)...); + } +}; + +} // namespace internal + +inline namespace literals { + +inline internal::UdlFormat +operator"" _format(const char *s, std::size_t) { return {s}; } +inline internal::UdlFormat +operator"" _format(const wchar_t *s, std::size_t) { return {s}; } + +} // inline namespace literals +} // namespace fmt +#endif // FMT_USE_USER_DEFINED_LITERALS + // Restore warnings. #if FMT_GCC_VERSION >= 406 # pragma GCC diagnostic pop diff --git a/test/format-test.cc b/test/format-test.cc index 184985240df7..b95c499a0d0d 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -1602,3 +1602,12 @@ TEST(FormatTest, MaxArgs) { fmt::format("{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 'd', 'e')); } + +#if FMT_USE_USER_DEFINED_LITERALS +using namespace fmt::literals; + +TEST(LiteralsTest, Format) { + EXPECT_EQ(format("{}c{}", "ab", 1), "{}c{}"_format("ab", 1)); + EXPECT_EQ(format(L"{}c{}", L"ab", 1), L"{}c{}"_format(L"ab", 1)); +} +#endif // FMT_USE_USER_DEFINED_LITERALS From bc6010cc211e20942948ae9bce4939dc1eea590f Mon Sep 17 00:00:00 2001 From: Dean Moldovan Date: Sun, 27 Sep 2015 04:09:37 +0200 Subject: [PATCH 2/2] Add _a literal for named arguments --- format.h | 15 +++++++++++++++ test/format-test.cc | 13 +++++++++++++ 2 files changed, 28 insertions(+) diff --git a/format.h b/format.h index b85ddcb15a65..e5e9153778ce 100644 --- a/format.h +++ b/format.h @@ -3030,6 +3030,16 @@ struct UdlFormat { } }; +template +struct UdlArg { + const Char *str; + + template + NamedArg operator=(T &&value) const { + return {str, std::forward(value)}; + } +}; + } // namespace internal inline namespace literals { @@ -3039,6 +3049,11 @@ operator"" _format(const char *s, std::size_t) { return {s}; } inline internal::UdlFormat operator"" _format(const wchar_t *s, std::size_t) { return {s}; } +inline internal::UdlArg +operator"" _a(const char *s, std::size_t) { return {s}; } +inline internal::UdlArg +operator"" _a(const wchar_t *s, std::size_t) { return {s}; } + } // inline namespace literals } // namespace fmt #endif // FMT_USE_USER_DEFINED_LITERALS diff --git a/test/format-test.cc b/test/format-test.cc index b95c499a0d0d..c189f99050e3 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -1610,4 +1610,17 @@ TEST(LiteralsTest, Format) { EXPECT_EQ(format("{}c{}", "ab", 1), "{}c{}"_format("ab", 1)); EXPECT_EQ(format(L"{}c{}", L"ab", 1), L"{}c{}"_format(L"ab", 1)); } + +TEST(LiteralsTest, NamedArg) { + EXPECT_EQ(format("{first}{second}{first}{third}", + fmt::arg("first", "abra"), fmt::arg("second", "cad"), + fmt::arg("third", 99)), + format("{first}{second}{first}{third}", + "first"_a="abra", "second"_a="cad", "third"_a=99)); + EXPECT_EQ(format(L"{first}{second}{first}{third}", + fmt::arg(L"first", L"abra"), fmt::arg(L"second", L"cad"), + fmt::arg(L"third", 99)), + format(L"{first}{second}{first}{third}", + L"first"_a=L"abra", L"second"_a=L"cad", L"third"_a=99)); +} #endif // FMT_USE_USER_DEFINED_LITERALS