diff --git a/include/fmt/ranges.h b/include/fmt/ranges.h index 10429fc8..8b7c9aad 100644 --- a/include/fmt/ranges.h +++ b/include/fmt/ranges.h @@ -390,22 +390,35 @@ using range_formatter_type = conditional_t< template using maybe_const_range = conditional_t::value, const R, R>; + +// is_nonrecursive_range depends on fmt::is_range::value == true. +// It exists to ensure short-circuit evaluation in the constraint of the +// formatter specialization below. A similar approach is used in +// https://wg21.link/p2286. +template +struct is_nonrecursive_range : bool_constant< + !std::is_same, R>::value> {}; + +// is_formattable_delayed depends on is_nonrecursive_range::value == true. +// It exists to ensure short-circuit evaluation in the constraint of the +// formatter specialization below. +template +struct is_formattable_delayed : disjunction< + is_formattable>, Char>, + has_fallback_formatter>, Char>> {}; + } // namespace detail template struct formatter< R, Char, enable_if_t< - conjunction -// Workaround a bug in MSVC 2017 and earlier. -#if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1920 - , - disjunction< - is_formattable>, - Char>, - detail::has_fallback_formatter< - detail::uncvref_type>, Char> - > + conjunction, + detail::is_nonrecursive_range +// Workaround a bug in MSVC 2015 and earlier. +#if !FMT_MSC_VERSION || FMT_MSC_VERSION > 1900 + , + detail::is_formattable_delayed #endif >::value >> { diff --git a/include/fmt/std.h b/include/fmt/std.h index 227f4841..41d2b283 100644 --- a/include/fmt/std.h +++ b/include/fmt/std.h @@ -57,10 +57,6 @@ inline void write_escaped_path( } // namespace detail -#if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1920 -// For MSVC 2017 and earlier using the partial specialization -// would cause an ambiguity error, therefore we provide it only -// conditionally. template struct formatter : formatter> { @@ -73,7 +69,6 @@ struct formatter basic_string_view(quoted.data(), quoted.size()), ctx); } }; -#endif FMT_END_NAMESPACE #endif diff --git a/test/std-test.cc b/test/std-test.cc index fc8f72a0..c22b3e38 100644 --- a/test/std-test.cc +++ b/test/std-test.cc @@ -14,10 +14,7 @@ #include "gtest/gtest.h" TEST(std_test, path) { -// Test ambiguity problem described in #2954. We need to exclude compilers -// where the ambiguity problem cannot be solved for now. -#if defined(__cpp_lib_filesystem) && \ - (!FMT_MSC_VERSION || FMT_MSC_VERSION >= 1920) +#ifdef __cpp_lib_filesystem EXPECT_EQ(fmt::format("{:8}", std::filesystem::path("foo")), "\"foo\" "); EXPECT_EQ(fmt::format("{}", std::filesystem::path("foo\"bar.txt")), "\"foo\\\"bar.txt\""); @@ -37,10 +34,8 @@ TEST(std_test, path) { } TEST(ranges_std_test, format_vector_path) { -// Test ambiguity problem described in #2954. We need to exclude compilers -// where the ambiguity problem cannot be solved for now. -#if defined(__cpp_lib_filesystem) && \ - (!FMT_MSC_VERSION || FMT_MSC_VERSION >= 1920) +// Test ambiguity problem described in #2954. +#ifdef __cpp_lib_filesystem auto p = std::filesystem::path("foo/bar.txt"); auto c = std::vector{"abc", "def"}; EXPECT_EQ(fmt::format("path={}, range={}", p, c),