From 78c67157c1c74b366f92287b84969b2817955962 Mon Sep 17 00:00:00 2001 From: Alexey Ochapov Date: Tue, 16 Feb 2021 07:04:52 +0300 Subject: [PATCH] prepare tests, fix incorrect handling of named args with simple `{}` replacement fields --- include/fmt/compile.h | 22 +++++++++++++++++----- test/compile-test.cc | 39 ++++++++++++++++++++++++++++----------- 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/include/fmt/compile.h b/include/fmt/compile.h index 2f613db0..30ee85df 100644 --- a/include/fmt/compile.h +++ b/include/fmt/compile.h @@ -454,9 +454,14 @@ template struct field { template constexpr OutputIt format(OutputIt out, const Args&... args) const { - // This ensures that the argument type is convertile to `const T&`. - const T& arg = get(args...); - return write(out, arg); + if constexpr (is_named_arg::type>::value) { + decltype(T::value) arg = get(args...).value; + return write(out, arg); + } else { + // This ensures that the argument type is convertile to `const T&`. + const T& arg = get(args...); + return write(out, arg); + } } }; @@ -775,8 +780,15 @@ FMT_INLINE std::basic_string format(const S&, #ifdef __cpp_if_constexpr if constexpr (std::is_same::value) { constexpr basic_string_view str = S(); - if constexpr (str.size() == 2 && str[0] == '{' && str[1] == '}') - return fmt::to_string(detail::first(args...)); + if constexpr (str.size() == 2 && str[0] == '{' && str[1] == '}') { + auto first = detail::first(args...); + if constexpr (detail::is_named_arg::type>::value) { + return fmt::to_string(first.value); + } else { + return fmt::to_string(first); + } + } } #endif constexpr auto compiled = detail::compile(S()); diff --git a/test/compile-test.cc b/test/compile-test.cc index cab2e8b4..ce23c2f5 100644 --- a/test/compile-test.cc +++ b/test/compile-test.cc @@ -255,17 +255,34 @@ TEST(CompileTest, ManualOrdering) { } TEST(CompileTest, Named) { - EXPECT_EQ("41 43", fmt::format(FMT_COMPILE("{name1} {name2}"), - fmt::arg("name1", 41), fmt::arg("name2", 43))); - EXPECT_EQ("41 43", - fmt::format(FMT_COMPILE("{} {name2}"), 41, fmt::arg("name2", 43))); - EXPECT_EQ("41 43", - fmt::format(FMT_COMPILE("{name1} {}"), fmt::arg("name1", 41), 43)); - EXPECT_EQ("41 43", - fmt::format(FMT_COMPILE("{name1} {name2}"), fmt::arg("name1", 41), - fmt::arg("name2", 43), fmt::arg("name3", 42))); - EXPECT_EQ("41 43", fmt::format(FMT_COMPILE("{name2} {name1}"), - fmt::arg("name1", 43), fmt::arg("name2", 41))); + EXPECT_EQ("42", fmt::format(FMT_COMPILE("{}"), fmt::arg("arg", 42))); + EXPECT_EQ("41 43", fmt::format(FMT_COMPILE("{} {}"), fmt::arg("arg", 41), + fmt::arg("arg", 43))); + + EXPECT_EQ("foobar", + fmt::format(FMT_COMPILE("{a0}{a1}"), fmt::arg("a0", "foo"), + fmt::arg("a1", "bar"))); + EXPECT_EQ("foobar", + fmt::format(/*FMT_COMPILE(*/ "{}{a1}" /*)*/, fmt::arg("a0", "foo"), + fmt::arg("a1", "bar"))); + EXPECT_EQ("foofoo", + fmt::format(/*FMT_COMPILE(*/ "{a0}{}" /*)*/, fmt::arg("a0", "foo"), + fmt::arg("a1", "bar"))); + EXPECT_EQ("foobar", + fmt::format(/*FMT_COMPILE(*/ "{a0}{1}" /*)*/, fmt::arg("a0", "foo"), + fmt::arg("a1", "bar"))); + EXPECT_EQ("foobar", + fmt::format(/*FMT_COMPILE(*/ "{0}{a1}" /*)*/, fmt::arg("a0", "foo"), + fmt::arg("a1", "bar"))); + + EXPECT_EQ("foobar", + fmt::format(FMT_COMPILE("{}{a1}"), "foo", fmt::arg("a1", "bar"))); + EXPECT_EQ("foobar", + fmt::format(FMT_COMPILE("{a0}{a1}"), fmt::arg("a1", "bar"), + fmt::arg("a2", "baz"), fmt::arg("a0", "foo"))); + EXPECT_EQ(" bar foo ", + fmt::format(FMT_COMPILE(" {foo} {bar} "), fmt::arg("foo", "bar"), + fmt::arg("bar", "foo"))); EXPECT_THROW(fmt::format(FMT_COMPILE("{invalid}"), fmt::arg("valid", 42)), fmt::format_error);