fix custom types formatting at compile-time, add test
This commit is contained in:
parent
8c1b22ba6d
commit
9976869549
@ -1140,7 +1140,7 @@ template <typename Context> class value {
|
||||
FMT_INLINE value(const named_arg_info<char_type>* args, size_t size)
|
||||
: named_args{args, size} {}
|
||||
|
||||
template <typename T> FMT_INLINE value(const T& val) {
|
||||
template <typename T> FMT_CONSTEXPR FMT_INLINE value(const T& val) {
|
||||
custom.value = &val;
|
||||
// Get the formatter type through the context to allow different contexts
|
||||
// have different extension points, e.g. `formatter<T>` for `format` and
|
||||
|
@ -1935,10 +1935,11 @@ OutputIt write(OutputIt out, const T* value,
|
||||
}
|
||||
|
||||
template <typename Char, typename OutputIt, typename T>
|
||||
auto write(OutputIt out, const T& value) -> typename std::enable_if<
|
||||
mapped_type_constant<T, basic_format_context<OutputIt, Char>>::value ==
|
||||
type::custom_type,
|
||||
OutputIt>::type {
|
||||
FMT_CONSTEXPR auto write(OutputIt out, const T& value) ->
|
||||
typename std::enable_if<
|
||||
mapped_type_constant<T, basic_format_context<OutputIt, Char>>::value ==
|
||||
type::custom_type,
|
||||
OutputIt>::type {
|
||||
using context_type = basic_format_context<OutputIt, Char>;
|
||||
using formatter_type =
|
||||
conditional_t<has_formatter<T, context_type>::value,
|
||||
|
@ -53,17 +53,6 @@ TEST(iterator_test, truncating_back_inserter) {
|
||||
EXPECT_EQ(buffer, "42");
|
||||
}
|
||||
|
||||
struct test_formattable {};
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
template <> struct formatter<test_formattable> : formatter<const char*> {
|
||||
template <typename FormatContext>
|
||||
auto format(test_formattable, FormatContext& ctx) -> decltype(ctx.out()) {
|
||||
return formatter<const char*>::format("foo", ctx);
|
||||
}
|
||||
};
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
TEST(compile_test, compile_fallback) {
|
||||
// FMT_COMPILE should fallback on runtime formatting when `if constexpr` is
|
||||
// not available.
|
||||
@ -71,6 +60,27 @@ TEST(compile_test, compile_fallback) {
|
||||
}
|
||||
|
||||
#ifdef __cpp_if_constexpr
|
||||
struct test_formattable {};
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
template <> struct formatter<test_formattable> : formatter<const char*> {
|
||||
char word_spec = 'f';
|
||||
constexpr auto parse(format_parse_context& ctx) {
|
||||
auto it = ctx.begin(), end = ctx.end();
|
||||
if (it == end || *it == '}') return it;
|
||||
if (it != end && (*it == 'f' || *it == 'b')) word_spec = *it++;
|
||||
if (it != end && *it != '}') throw format_error("invalid format");
|
||||
return it;
|
||||
}
|
||||
template <typename FormatContext>
|
||||
constexpr auto format(test_formattable, FormatContext& ctx) const
|
||||
-> decltype(ctx.out()) {
|
||||
return formatter<const char*>::format(word_spec == 'f' ? "foo" : "bar",
|
||||
ctx);
|
||||
}
|
||||
};
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
TEST(compile_test, format_default) {
|
||||
EXPECT_EQ("42", fmt::format(FMT_COMPILE("{}"), 42));
|
||||
EXPECT_EQ("42", fmt::format(FMT_COMPILE("{}"), 42u));
|
||||
@ -336,6 +346,11 @@ TEST(compile_time_formatting_test, combination) {
|
||||
EXPECT_EQ(" -42", test_format<5>(FMT_COMPILE("{:{}}"), -42, 4));
|
||||
}
|
||||
|
||||
TEST(compile_time_formatting_test, custom_type) {
|
||||
EXPECT_EQ("foo", test_format<4>(FMT_COMPILE("{}"), test_formattable()));
|
||||
EXPECT_EQ("bar", test_format<4>(FMT_COMPILE("{:b}"), test_formattable()));
|
||||
}
|
||||
|
||||
TEST(compile_time_formatting_test, multibyte_fill) {
|
||||
EXPECT_EQ("жж42", test_format<8>(FMT_COMPILE("{:ж>4}"), 42));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user