mirror of
https://github.com/shadps4-emu/ext-fmt.git
synced 2024-11-23 17:59:52 +00:00
Fix container adaptor formatting
This commit is contained in:
parent
581c6292c9
commit
655046d24f
@ -157,8 +157,7 @@ struct has_mutable_begin_end<
|
||||
decltype(detail::range_end(std::declval<T>())),
|
||||
// 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 <typename T>
|
||||
struct is_range_<T, void>
|
||||
@ -663,7 +662,7 @@ struct formatter<tuple_join_view<Char, T...>, 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 <typename T> class is_container_adaptor_like {
|
||||
template <typename U> static auto check(U* p) -> typename U::container_type;
|
||||
@ -673,20 +672,27 @@ template <typename T> class is_container_adaptor_like {
|
||||
static constexpr const bool value =
|
||||
!std::is_void<decltype(check<T>(nullptr))>::value;
|
||||
};
|
||||
|
||||
template <typename Container> 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 <typename T, typename Char>
|
||||
struct formatter<T, Char,
|
||||
enable_if_t<detail::is_container_adaptor_like<T>::value>>
|
||||
: formatter<typename T::container_type, Char> {
|
||||
: formatter<detail::all<typename T::container_type>, Char> {
|
||||
using all = detail::all<typename T::container_type>;
|
||||
template <typename FormatContext>
|
||||
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<typename T::container_type>::format(getter::get(t), ctx);
|
||||
return formatter<all>::format(getter::get(t), ctx);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -12,10 +12,10 @@
|
||||
#include "fmt/ranges.h"
|
||||
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stack>
|
||||
#include <queue>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
@ -447,10 +447,8 @@ TEST(ranges_test, container_adaptor) {
|
||||
std::stack<char, std::string> 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']");
|
||||
}
|
||||
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user