From 655046d24f2ffeaf44e483412df1c727a273764d Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Fri, 10 Feb 2023 09:45:27 -0800 Subject: [PATCH] Fix container adaptor formatting --- include/fmt/ranges.h | 20 +++++++++++++------- test/ranges-test.cc | 10 ++++------ 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/include/fmt/ranges.h b/include/fmt/ranges.h index 3377efca..8912fe93 100644 --- a/include/fmt/ranges.h +++ b/include/fmt/ranges.h @@ -157,8 +157,7 @@ struct has_mutable_begin_end< decltype(detail::range_end(std::declval())), // the extra int here is because older versions of MSVC don't // SFINAE properly unless there are distinct types - int>> - : std::true_type {}; + int>> : std::true_type {}; template struct is_range_ @@ -663,7 +662,7 @@ struct formatter, Char> { }; namespace detail { -// Check if T has an interface like container adapter (e.g. std::stack, +// Check if T has an interface like a container adaptor (e.g. std::stack, // std::queue, std::priority_queue). template class is_container_adaptor_like { template static auto check(U* p) -> typename U::container_type; @@ -673,20 +672,27 @@ template class is_container_adaptor_like { static constexpr const bool value = !std::is_void(nullptr))>::value; }; + +template struct all { + const Container& c; + auto begin() const -> typename Container::const_iterator { return c.begin(); } + auto end() const -> typename Container::const_iterator { return c.end(); }; +}; } // namespace detail template struct formatter::value>> - : formatter { + : formatter, Char> { + using all = detail::all; template auto format(const T& t, FormatContext& ctx) const -> decltype(ctx.out()) { struct getter : T { - static auto get(const T& t) -> const typename T::container_type& { - return t.*(&getter::c); // Access c through the derived class. + static auto get(const T& t) -> all { + return {t.*(&getter::c)}; // Access c through the derived class. } }; - return formatter::format(getter::get(t), ctx); + return formatter::format(getter::get(t), ctx); } }; diff --git a/test/ranges-test.cc b/test/ranges-test.cc index 16fd0734..26e3362a 100644 --- a/test/ranges-test.cc +++ b/test/ranges-test.cc @@ -12,10 +12,10 @@ #include "fmt/ranges.h" #include +#include +#include #include #include -#include -#include #include "gtest/gtest.h" @@ -447,10 +447,8 @@ TEST(ranges_test, container_adaptor) { std::stack s; s.push('a'); s.push('b'); - // Note: The output is formatted as a string because the underlying - // container is a string. This behavior is conforming to the standard - // [container.adaptors.format]. - EXPECT_EQ(fmt::format("{}", s), "ab"); + // See https://cplusplus.github.io/LWG/issue3881. + EXPECT_EQ(fmt::format("{}", s), "['a', 'b']"); } {