Make compile-time checks work with fallback formatter (#1088)

This commit is contained in:
Victor Zverovich 2019-03-21 19:02:19 -07:00
parent 7ad3015f5b
commit da0ea4161a
3 changed files with 16 additions and 7 deletions

View File

@ -674,6 +674,15 @@ template <typename Context> struct custom_value {
Context& ctx);
};
template <typename T, typename Context>
struct is_formattable {
enum {
value = !is_constructible<
typename Context::template formatter_type<T>::type,
internal::dummy_formatter_arg>::value
};
};
// A formatting argument value.
template <typename Context> class value {
public:
@ -721,14 +730,10 @@ template <typename Context> class value {
// Get the formatter type through the context to allow different contexts
// have different extension points, e.g. `formatter<T>` for `format` and
// `printf_formatter<T>` for `printf`.
typedef typename Context::template formatter_type<T>::type formatter;
enum {
formattable =
!is_constructible<formatter, internal::dummy_formatter_arg>::value
};
custom.format = &format_custom_arg<
T, typename std::conditional<
formattable, formatter,
is_formattable<T, Context>::value,
typename Context::template formatter_type<T>::type,
internal::fallback_formatter<T, char_type>>::type>;
}

View File

@ -2136,7 +2136,10 @@ template <typename T, typename ParseContext>
FMT_CONSTEXPR const typename ParseContext::char_type* parse_format_specs(
ParseContext& ctx) {
// GCC 7.2 requires initializer.
formatter<T, typename ParseContext::char_type> f{};
typedef typename ParseContext::char_type char_type;
typename std::conditional<
is_formattable<T, format_context>::value,
formatter<T, char_type>, internal::fallback_formatter<T, char_type>>::type f;
return f.parse(ctx);
}

View File

@ -173,6 +173,7 @@ TEST(OStreamTest, Join) {
#if FMT_USE_CONSTEXPR
TEST(OStreamTest, ConstexprString) {
EXPECT_EQ("42", format(fmt("{}"), std::string("42")));
EXPECT_EQ("a string", format(fmt("{0}"), TestString("a string")));
}
#endif