Make formatter override implicit conversion to a C string

This commit is contained in:
Victor Zverovich 2020-02-07 18:47:48 -08:00
parent 24924128e3
commit 1f1b50707c
3 changed files with 25 additions and 18 deletions

View File

@ -900,7 +900,8 @@ template <typename Context> struct arg_mapper {
template <typename T, template <typename T,
FMT_ENABLE_IF( FMT_ENABLE_IF(
std::is_constructible<basic_string_view<char_type>, T>::value && std::is_constructible<basic_string_view<char_type>, T>::value &&
!is_string<T>::value)> !is_string<T>::value && !has_formatter<T, Context>::value &&
!has_fallback_formatter<T, Context>::value)>
FMT_CONSTEXPR basic_string_view<char_type> map(const T& val) { FMT_CONSTEXPR basic_string_view<char_type> map(const T& val) {
return basic_string_view<char_type>(val); return basic_string_view<char_type>(val);
} }
@ -909,7 +910,8 @@ template <typename Context> struct arg_mapper {
FMT_ENABLE_IF( FMT_ENABLE_IF(
std::is_constructible<std_string_view<char_type>, T>::value && std::is_constructible<std_string_view<char_type>, T>::value &&
!std::is_constructible<basic_string_view<char_type>, T>::value && !std::is_constructible<basic_string_view<char_type>, T>::value &&
!is_string<T>::value && !has_formatter<T, Context>::value)> !is_string<T>::value && !has_formatter<T, Context>::value &&
!has_fallback_formatter<T, Context>::value)>
FMT_CONSTEXPR basic_string_view<char_type> map(const T& val) { FMT_CONSTEXPR basic_string_view<char_type> map(const T& val) {
return std_string_view<char_type>(val); return std_string_view<char_type>(val);
} }
@ -946,10 +948,8 @@ template <typename Context> struct arg_mapper {
typename T, typename T,
FMT_ENABLE_IF( FMT_ENABLE_IF(
!is_string<T>::value && !is_char<T>::value && !is_string<T>::value && !is_char<T>::value &&
!std::is_constructible<basic_string_view<char_type>, T>::value &&
(has_formatter<T, Context>::value || (has_formatter<T, Context>::value ||
(has_fallback_formatter<T, Context>::value && has_fallback_formatter<T, Context>::value))>
!std::is_constructible<std_string_view<char_type>, T>::value)))>
FMT_CONSTEXPR const T& map(const T& val) { FMT_CONSTEXPR const T& map(const T& val) {
return val; return val;
} }

View File

@ -469,6 +469,10 @@ struct convertible_to_int {
operator int() const { return 42; } operator int() const { return 42; }
}; };
struct convertible_to_c_string {
operator const char*() const { return "foo"; }
};
FMT_BEGIN_NAMESPACE FMT_BEGIN_NAMESPACE
template <> struct formatter<convertible_to_int> { template <> struct formatter<convertible_to_int> {
auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
@ -478,10 +482,21 @@ template <> struct formatter<convertible_to_int> {
return std::copy_n("foo", 3, ctx.out()); return std::copy_n("foo", 3, ctx.out());
} }
}; };
template <> struct formatter<convertible_to_c_string> {
auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
return ctx.begin();
}
auto format(convertible_to_c_string, format_context& ctx)
-> decltype(ctx.out()) {
return std::copy_n("bar", 3, ctx.out());
}
};
FMT_END_NAMESPACE FMT_END_NAMESPACE
TEST(CoreTest, FormatterOverridesImplicitConversion) { TEST(CoreTest, FormatterOverridesImplicitConversion) {
EXPECT_EQ(fmt::format("{}", convertible_to_int()), "foo"); EXPECT_EQ(fmt::format("{}", convertible_to_int()), "foo");
EXPECT_EQ(fmt::format("{}", convertible_to_c_string()), "bar");
} }
namespace my_ns { namespace my_ns {

View File

@ -264,17 +264,13 @@ struct explicitly_convertible_to_string_like {
} }
}; };
TEST(FormatterTest, FormatExplicitlyConvertibleToStringLike) {
EXPECT_EQ("foo", fmt::format("{}", explicitly_convertible_to_string_like()));
}
std::ostream& operator<<(std::ostream& os, std::ostream& operator<<(std::ostream& os,
explicitly_convertible_to_string_like) { explicitly_convertible_to_string_like) {
return os << "bar"; return os << "bar";
} }
TEST(FormatterTest, FormatExplicitlyConvertibleToStringLikeIgnoreInserter) { TEST(FormatterTest, FormatExplicitlyConvertibleToStringLike) {
EXPECT_EQ("foo", fmt::format("{}", explicitly_convertible_to_string_like())); EXPECT_EQ("bar", fmt::format("{}", explicitly_convertible_to_string_like()));
} }
#ifdef FMT_USE_STRING_VIEW #ifdef FMT_USE_STRING_VIEW
@ -284,17 +280,13 @@ struct explicitly_convertible_to_std_string_view {
} }
}; };
TEST(FormatterTest, FormatExplicitlyConvertibleToStdStringView) {
EXPECT_EQ("foo", fmt::format("{}", explicitly_convertible_to_string_like()));
}
std::ostream& operator<<(std::ostream& os, std::ostream& operator<<(std::ostream& os,
explicitly_convertible_to_std_string_view) { explicitly_convertible_to_std_string_view) {
return os << "bar"; return os << "bar";
} }
TEST(FormatterTest, FormatExplicitlyConvertibleToStdStringViewIgnoreInserter) { TEST(FormatterTest, FormatExplicitlyConvertibleToStdStringView) {
EXPECT_EQ("foo", EXPECT_EQ("bar", fmt::format("{}", explicitly_convertible_to_string_like()));
fmt::format("{}", explicitly_convertible_to_std_string_view()));
} }
#endif // FMT_USE_STRING_VIEW #endif // FMT_USE_STRING_VIEW