mirror of
https://github.com/fmtlib/fmt.git
synced 2025-04-16 14:42:25 +00:00
Disable range formatter if value type is not formattable (#1885)
This commit is contained in:
parent
c46a8de4e1
commit
2f7e08856b
@ -157,6 +157,9 @@ template <class Tuple, class F> void for_each(Tuple&& tup, F&& f) {
|
|||||||
for_each(indexes, std::forward<Tuple>(tup), std::forward<F>(f));
|
for_each(indexes, std::forward<Tuple>(tup), std::forward<F>(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Range>
|
||||||
|
using value_type = remove_cvref_t<decltype(*std::declval<Range>().begin())>;
|
||||||
|
|
||||||
template <typename Arg, FMT_ENABLE_IF(!is_like_std_string<
|
template <typename Arg, FMT_ENABLE_IF(!is_like_std_string<
|
||||||
typename std::decay<Arg>::type>::value)>
|
typename std::decay<Arg>::type>::value)>
|
||||||
FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const Arg&) {
|
FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const Arg&) {
|
||||||
@ -182,7 +185,6 @@ FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const char) {
|
|||||||
FMT_CONSTEXPR const wchar_t* format_str_quoted(bool add_space, const wchar_t) {
|
FMT_CONSTEXPR const wchar_t* format_str_quoted(bool add_space, const wchar_t) {
|
||||||
return add_space ? L" '{}'" : L"'{}'";
|
return add_space ? L" '{}'" : L"'{}'";
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
template <typename T> struct is_tuple_like {
|
template <typename T> struct is_tuple_like {
|
||||||
@ -246,9 +248,15 @@ template <typename T, typename Char> struct is_range {
|
|||||||
!std::is_constructible<detail::std_string_view<Char>, T>::value;
|
!std::is_constructible<detail::std_string_view<Char>, T>::value;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename RangeT, typename Char>
|
template <typename T, typename Char>
|
||||||
struct formatter<RangeT, Char,
|
struct formatter<
|
||||||
enable_if_t<fmt::is_range<RangeT, Char>::value>> {
|
T, Char,
|
||||||
|
enable_if_t<fmt::is_range<T, Char>::value
|
||||||
|
// Workaround a bug in MSVC 2017 and earlier.
|
||||||
|
#if !FMT_MSC_VER || FMT_MSC_VER >= 1927
|
||||||
|
&& has_formatter<detail::value_type<T>, format_context>::value
|
||||||
|
#endif
|
||||||
|
>> {
|
||||||
formatting_range<Char> formatting;
|
formatting_range<Char> formatting;
|
||||||
|
|
||||||
template <typename ParseContext>
|
template <typename ParseContext>
|
||||||
@ -257,8 +265,7 @@ struct formatter<RangeT, Char,
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename FormatContext>
|
template <typename FormatContext>
|
||||||
typename FormatContext::iterator format(const RangeT& values,
|
typename FormatContext::iterator format(const T& values, FormatContext& ctx) {
|
||||||
FormatContext& ctx) {
|
|
||||||
auto out = detail::copy(formatting.prefix, ctx.out());
|
auto out = detail::copy(formatting.prefix, ctx.out());
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
auto it = values.begin();
|
auto it = values.begin();
|
||||||
|
@ -141,13 +141,16 @@ TEST(RangesTest, FormatStringLike) {
|
|||||||
#endif // FMT_USE_STRING_VIEW
|
#endif // FMT_USE_STRING_VIEW
|
||||||
|
|
||||||
struct zstring_sentinel {};
|
struct zstring_sentinel {};
|
||||||
|
|
||||||
bool operator==(const char* p, zstring_sentinel) { return *p == '\0'; }
|
bool operator==(const char* p, zstring_sentinel) { return *p == '\0'; }
|
||||||
bool operator!=(const char* p, zstring_sentinel) { return *p != '\0'; }
|
bool operator!=(const char* p, zstring_sentinel) { return *p != '\0'; }
|
||||||
|
|
||||||
struct zstring {
|
struct zstring {
|
||||||
const char* p;
|
const char* p;
|
||||||
const char* begin() const { return p; }
|
const char* begin() const { return p; }
|
||||||
zstring_sentinel end() const { return {}; }
|
zstring_sentinel end() const { return {}; }
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST(RangesTest, JoinSentinel) {
|
TEST(RangesTest, JoinSentinel) {
|
||||||
zstring hello{"hello"};
|
zstring hello{"hello"};
|
||||||
EXPECT_EQ("{'h', 'e', 'l', 'l', 'o'}", fmt::format("{}", hello));
|
EXPECT_EQ("{'h', 'e', 'l', 'l', 'o'}", fmt::format("{}", hello));
|
||||||
@ -189,3 +192,12 @@ TEST(RangesTest, JoinRange) {
|
|||||||
const std::vector<int> z(3u, 0);
|
const std::vector<int> z(3u, 0);
|
||||||
EXPECT_EQ("0,0,0", fmt::format("{}", fmt::join(z, ",")));
|
EXPECT_EQ("0,0,0", fmt::format("{}", fmt::join(z, ",")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !FMT_MSC_VER || FMT_MSC_VER >= 1927
|
||||||
|
struct unformattable {};
|
||||||
|
|
||||||
|
TEST(RangesTest, UnformattableRange) {
|
||||||
|
EXPECT_FALSE((fmt::has_formatter<std::vector<unformattable>,
|
||||||
|
fmt::format_context>::value));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user