is_formattable -> has_formatter

This commit is contained in:
Victor Zverovich 2019-06-07 06:51:21 -07:00
parent b3cf8613b1
commit 40779749ac
3 changed files with 10 additions and 8 deletions

View File

@ -492,6 +492,12 @@ struct convert_to_int : bool_constant<!std::is_arithmetic<T>::value &&
namespace internal { namespace internal {
// Specifies if T has an enabled formatter specialization. The type can be
// formattable even if it doesn't have a formatter e.g. via conversion.
template <typename T, typename Context>
using has_formatter =
std::is_constructible<typename Context::template formatter_type<T>>;
/** A contiguous memory buffer with an optional growing ability. */ /** A contiguous memory buffer with an optional growing ability. */
template <typename T> class buffer { template <typename T> class buffer {
private: private:
@ -675,10 +681,6 @@ template <typename Context> struct custom_value {
void (*format)(const void* arg, parse_context& parse_ctx, Context& ctx); void (*format)(const void* arg, parse_context& parse_ctx, Context& ctx);
}; };
template <typename T, typename Context>
using is_formattable =
std::is_constructible<typename Context::template formatter_type<T>>;
// A formatting argument value. // A formatting argument value.
template <typename Context> class value { template <typename Context> class value {
public: public:
@ -727,7 +729,7 @@ template <typename Context> class value {
// 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`.
custom.format = &format_custom_arg< custom.format = &format_custom_arg<
T, conditional_t<is_formattable<T, Context>::value, T, conditional_t<has_formatter<T, Context>::value,
typename Context::template formatter_type<T>, typename Context::template formatter_type<T>,
internal::fallback_formatter<T, char_type>>>; internal::fallback_formatter<T, char_type>>>;
} }
@ -875,7 +877,7 @@ inline init<C, const T&, custom_type> make_value(const T& val) {
template <typename C, typename T, template <typename C, typename T,
FMT_ENABLE_IF(std::is_class<T>::value&& std::is_convertible< FMT_ENABLE_IF(std::is_class<T>::value&& std::is_convertible<
T, int>::value&& is_formattable<T, C>::value && T, int>::value&& has_formatter<T, C>::value &&
!std::is_same<T, typename C::char_type>::value)> !std::is_same<T, typename C::char_type>::value)>
inline init<C, const T&, custom_type> make_value(const T& val) { inline init<C, const T&, custom_type> make_value(const T& val) {
return val; return val;

View File

@ -2179,7 +2179,7 @@ FMT_CONSTEXPR const typename ParseContext::char_type* parse_format_specs(
ParseContext& ctx) { ParseContext& ctx) {
// GCC 7.2 requires initializer. // GCC 7.2 requires initializer.
typedef typename ParseContext::char_type char_type; typedef typename ParseContext::char_type char_type;
conditional_t<is_formattable<T, buffer_context<char_type>>::value, conditional_t<has_formatter<T, buffer_context<char_type>>::value,
formatter<T, char_type>, formatter<T, char_type>,
internal::fallback_formatter<T, char_type>> internal::fallback_formatter<T, char_type>>
f; f;

View File

@ -1877,7 +1877,7 @@ enum TestEnum { A };
TEST(FormatTest, Enum) { EXPECT_EQ("0", fmt::format("{}", A)); } TEST(FormatTest, Enum) { EXPECT_EQ("0", fmt::format("{}", A)); }
TEST(FormatTest, FormatterNotSpecialized) { TEST(FormatTest, FormatterNotSpecialized) {
EXPECT_FALSE((fmt::internal::is_formattable< EXPECT_FALSE((fmt::internal::has_formatter<
fmt::formatter<TestEnum>, fmt::format_context>::value)); fmt::formatter<TestEnum>, fmt::format_context>::value));
} }