Skip to content

Commit b7ca1f8

Browse files
committed
Allow custom FP formatters
1 parent 45b772f commit b7ca1f8

File tree

4 files changed

+36
-31
lines changed

4 files changed

+36
-31
lines changed

Diff for: include/fmt/base.h

+14-8
Original file line numberDiff line numberDiff line change
@@ -1442,9 +1442,12 @@ template <typename Context> struct arg_mapper {
14421442
return {};
14431443
}
14441444

1445-
FMT_MAP_API auto map(float val) -> float { return val; }
1446-
FMT_MAP_API auto map(double val) -> double { return val; }
1447-
FMT_MAP_API auto map(long double val) -> long double { return val; }
1445+
// Use references to allow custom floating point formatters.
1446+
template <typename T, FMT_ENABLE_IF(std::is_fundamental<T>::value &&
1447+
!std::is_integral<T>::value)>
1448+
FMT_MAP_API auto map(const T& val) -> const T& {
1449+
return val;
1450+
}
14481451

14491452
FMT_MAP_API auto map(char_type* val) -> const char_type* { return val; }
14501453
FMT_MAP_API auto map(const char_type* val) -> const char_type* { return val; }
@@ -1527,7 +1530,8 @@ template <typename Context> struct arg_mapper {
15271530
// A type constant after applying arg_mapper<Context>.
15281531
template <typename T, typename Context>
15291532
using mapped_type_constant =
1530-
type_constant<decltype(arg_mapper<Context>().map(std::declval<const T&>())),
1533+
type_constant<remove_cvref_t<decltype(arg_mapper<Context>().map(
1534+
std::declval<const T&>()))>,
15311535
typename Context::char_type>;
15321536

15331537
enum { packed_arg_bits = 4 };
@@ -2650,10 +2654,12 @@ FMT_CONSTEXPR auto parse_format_specs(ParseContext& ctx)
26502654
-> decltype(ctx.begin()) {
26512655
using char_type = typename ParseContext::char_type;
26522656
using context = buffered_context<char_type>;
2653-
using mapped_type = conditional_t<
2654-
mapped_type_constant<T, context>::value != type::custom_type,
2655-
decltype(arg_mapper<context>().map(std::declval<const T&>())),
2656-
typename strip_named_arg<T>::type>;
2657+
using mapped_type =
2658+
conditional_t<mapped_type_constant<T, context>::value !=
2659+
type::custom_type,
2660+
remove_cvref_t<decltype(arg_mapper<context>().map(
2661+
std::declval<const T&>()))>,
2662+
typename strip_named_arg<T>::type>;
26572663
#if defined(__cpp_if_constexpr)
26582664
if constexpr (std::is_default_constructible<
26592665
formatter<mapped_type, char_type>>::value) {

Diff for: include/fmt/format.h

+13-17
Original file line numberDiff line numberDiff line change
@@ -761,28 +761,22 @@ using is_integer =
761761
# define FMT_USE_LONG_DOUBLE 1
762762
#endif
763763

764-
#ifndef FMT_USE_FLOAT128
765-
# ifdef __clang__
766-
// Clang emulates GCC, so it has to appear early.
767-
# if FMT_HAS_INCLUDE(<quadmath.h>)
768-
# define FMT_USE_FLOAT128 1
769-
# endif
770-
# elif defined(__GNUC__)
771-
// GNU C++:
772-
# if defined(_GLIBCXX_USE_FLOAT128) && !defined(__STRICT_ANSI__)
773-
# define FMT_USE_FLOAT128 1
774-
# endif
775-
# endif
776-
# ifndef FMT_USE_FLOAT128
777-
# define FMT_USE_FLOAT128 0
778-
# endif
764+
#if defined(FMT_USE_FLOAT128)
765+
// Use the provided definition.
766+
#elif FMT_CLANG_VERSION && FMT_HAS_INCLUDE(<quadmath.h>)
767+
# define FMT_USE_FLOAT128 1
768+
#elif FMT_GCC_VERSION && defined(_GLIBCXX_USE_FLOAT128) && \
769+
!defined(__STRICT_ANSI__)
770+
# define FMT_USE_FLOAT128 1
771+
#else
772+
# define FMT_USE_FLOAT128 0
779773
#endif
780-
781774
#if FMT_USE_FLOAT128
782775
using float128 = __float128;
783776
#else
784777
using float128 = void;
785778
#endif
779+
786780
template <typename T> using is_float128 = std::is_same<T, float128>;
787781

788782
template <typename T>
@@ -3722,7 +3716,9 @@ FMT_CONSTEXPR auto write(OutputIt out, const T& value) -> enable_if_t<
37223716
template <typename Char, typename OutputIt, typename T,
37233717
typename Context = basic_format_context<OutputIt, Char>>
37243718
FMT_CONSTEXPR auto write(OutputIt out, const T& value)
3725-
-> enable_if_t<mapped_type_constant<T, Context>::value == type::custom_type,
3719+
-> enable_if_t<mapped_type_constant<T, Context>::value ==
3720+
type::custom_type &&
3721+
!is_floating_point<T>::value,
37263722
OutputIt> {
37273723
auto formatter = typename Context::template formatter_type<T>();
37283724
auto parse_ctx = typename Context::parse_context_type({});

Diff for: test/format-impl-test.cc

+6-2
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,9 @@ struct double_double {
290290
auto operator-() const -> double_double { return double_double(-a, -b); }
291291
};
292292

293-
auto format_as(double_double d) -> double { return d; }
293+
FMT_BEGIN_NAMESPACE
294+
template <> struct formatter<double_double> : formatter<double> {};
295+
FMT_END_NAMESPACE
294296

295297
bool operator>=(const double_double& lhs, const double_double& rhs) {
296298
return lhs.a + lhs.b >= rhs.a + rhs.b;
@@ -304,7 +306,9 @@ struct slow_float {
304306
auto operator-() const -> slow_float { return slow_float(-value); }
305307
};
306308

307-
auto format_as(slow_float f) -> float { return f; }
309+
FMT_BEGIN_NAMESPACE
310+
template <> struct formatter<slow_float> : formatter<float> {};
311+
FMT_END_NAMESPACE
308312

309313
namespace std {
310314
template <> struct is_floating_point<double_double> : std::true_type {};

Diff for: test/format-test.cc

+3-4
Original file line numberDiff line numberDiff line change
@@ -1793,15 +1793,14 @@ struct deadlockable {
17931793

17941794
FMT_BEGIN_NAMESPACE
17951795
template <> struct formatter<deadlockable> {
1796-
FMT_CONSTEXPR auto parse(fmt::format_parse_context& ctx)
1797-
-> decltype(ctx.begin()) {
1796+
FMT_CONSTEXPR auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
17981797
return ctx.begin();
17991798
}
18001799

1801-
auto format(const deadlockable& d, fmt::format_context& ctx) const
1800+
auto format(const deadlockable& d, format_context& ctx) const
18021801
-> decltype(ctx.out()) {
18031802
std::lock_guard<std::mutex> lock(d.mutex);
1804-
return fmt::format_to(ctx.out(), "{}", d.value);
1803+
return format_to(ctx.out(), "{}", d.value);
18051804
}
18061805
};
18071806
FMT_END_NAMESPACE

0 commit comments

Comments
 (0)