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); 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. // A formatting argument value.
template <typename Context> class value { template <typename Context> class value {
public: public:
@ -721,14 +730,10 @@ template <typename Context> class value {
// Get the formatter type through the context to allow different contexts // Get the formatter type through the context to allow different contexts
// have different extension points, e.g. `formatter<T>` for `format` and // have different extension points, e.g. `formatter<T>` for `format` and
// `printf_formatter<T>` for `printf`. // `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< custom.format = &format_custom_arg<
T, typename std::conditional< 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>; 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( FMT_CONSTEXPR const typename ParseContext::char_type* parse_format_specs(
ParseContext& ctx) { ParseContext& ctx) {
// GCC 7.2 requires initializer. // 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); return f.parse(ctx);
} }

View File

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