Simplify has_formatter

This commit is contained in:
Victor Zverovich
2024-09-16 19:48:02 -07:00
parent 7ce013971b
commit 0e62e5dc7c
2 changed files with 13 additions and 16 deletions

View File

@@ -1108,26 +1108,23 @@ struct use_formatter
!use_format_as<T>::value> {}; !use_format_as<T>::value> {};
template <typename Char, typename T> template <typename Char, typename T>
constexpr auto has_const_formatter_impl(T*) constexpr auto has_formatter_impl(T*)
-> decltype(formatter<T, Char>().format( -> decltype(formatter<remove_const_t<T>, Char>().format(
std::declval<const T&>(), std::declval<T&>(),
std::declval<buffered_context<Char>&>()), std::declval<buffered_context<Char>&>()),
true) { true) {
return true; return true;
} }
template <typename Char> constexpr auto has_const_formatter_impl(...) -> bool { template <typename Char> constexpr auto has_formatter_impl(...) -> bool {
return false; return false;
} }
template <typename T, typename Char> // T can be const-qualified to check if it is const-formattable.
constexpr auto has_const_formatter() -> bool { template <typename T, typename Char> constexpr auto has_formatter() -> bool {
return has_const_formatter_impl<Char>(static_cast<T*>(nullptr)); return has_formatter_impl<Char>(static_cast<T*>(nullptr));
} }
template <typename T, typename Char, typename U = remove_const_t<T>> template <typename T, typename Char>
struct formattable struct formattable : bool_constant<has_formatter<T, Char>()> {};
: bool_constant<has_const_formatter<U, Char>() ||
(std::is_constructible<formatter<U, Char>>::value &&
!std::is_const<T>::value)> {};
// Maps formatting argument types to natively supported types or user-defined // Maps formatting argument types to natively supported types or user-defined
// types with formatters. Returns void on errors to be SFINAE-friendly. // types with formatters. Returns void on errors to be SFINAE-friendly.
@@ -2223,7 +2220,7 @@ template <typename Context> class value {
auto f = Formatter(); auto f = Formatter();
parse_ctx.advance_to(f.parse(parse_ctx)); parse_ctx.advance_to(f.parse(parse_ctx));
using qualified_type = using qualified_type =
conditional_t<has_const_formatter<T, char_type>(), const T, T>; conditional_t<has_formatter<const T, char_type>(), const T, T>;
// format must be const for compatibility with std::format and compilation. // format must be const for compatibility with std::format and compilation.
const auto& cf = f; const auto& cf = f;
ctx.advance_to(cf.format(*static_cast<qualified_type*>(arg), ctx)); ctx.advance_to(cf.format(*static_cast<qualified_type*>(arg), ctx));

View File

@@ -784,10 +784,10 @@ TEST(base_test, format_explicitly_convertible_to_std_string_view) {
# endif # endif
#endif #endif
TEST(base_test, has_const_formatter) { TEST(base_test, has_formatter) {
EXPECT_TRUE((fmt::detail::has_const_formatter<const_formattable, char>())); EXPECT_TRUE((fmt::detail::has_formatter<const const_formattable, char>()));
EXPECT_FALSE( EXPECT_FALSE(
(fmt::detail::has_const_formatter<nonconst_formattable, char>())); (fmt::detail::has_formatter<const nonconst_formattable, char>()));
} }
TEST(base_test, format_nonconst) { TEST(base_test, format_nonconst) {