From 60740b7c24030b9fde5e7288e1cf41aef84fe7ba Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Sun, 1 Sep 2024 19:35:00 -0700 Subject: [PATCH] Cleanup base API --- include/fmt/base.h | 30 +++++++++++++----------------- include/fmt/ranges.h | 9 +++++++-- test/base-test.cc | 9 --------- test/format-test.cc | 4 ++-- test/ranges-test.cc | 3 +-- 5 files changed, 23 insertions(+), 32 deletions(-) diff --git a/include/fmt/base.h b/include/fmt/base.h index 965ada139201..378d79f94ea2 100644 --- a/include/fmt/base.h +++ b/include/fmt/base.h @@ -529,6 +529,8 @@ inline FMT_CONSTEXPR20 auto get_container(OutputIt it) -> } } // namespace detail +FMT_BEGIN_EXPORT + // Checks whether T is a container with contiguous storage. template struct is_contiguous : std::false_type {}; @@ -539,7 +541,6 @@ template struct is_contiguous : std::false_type {}; * compiled with a different `-std` option than the client code (which is not * recommended). */ -FMT_EXPORT template class basic_string_view { private: const Char* data_; @@ -633,7 +634,7 @@ template class basic_string_view { } }; -FMT_EXPORT using string_view = basic_string_view; +using string_view = basic_string_view; /// Specifies if `T` is a character type. Can be specialized by users. template struct is_char : std::false_type {}; @@ -657,28 +658,21 @@ using buffered_context = conditional_t::value, context, generic_context, Char>>; -FMT_EXPORT template class basic_format_arg; -FMT_EXPORT template class basic_format_args; -FMT_EXPORT template class dynamic_format_arg_store; +template class basic_format_arg; +template class basic_format_args; +template class dynamic_format_arg_store; // A separate type would result in shorter symbols but break ABI compatibility // between clang and gcc on ARM (#1919). using format_args = basic_format_args; // A formatter for objects of type T. -FMT_EXPORT template struct formatter { // A deleted default constructor indicates a disabled formatter. formatter() = delete; }; -// Specifies if T has an enabled formatter specialization. A type can be -// formattable even if it doesn't have a formatter e.g. via a conversion. -template -using has_formatter = - std::is_constructible>; - // This is defined in base.h instead of format.h to avoid injecting in std. // It is a template to avoid undesirable implicit conversions to std::byte. #ifdef __cpp_lib_byte @@ -688,6 +682,8 @@ inline auto format_as(T b) -> unsigned char { } #endif +FMT_END_EXPORT + namespace detail { // Constructs fmt::basic_string_view from types implicitly convertible @@ -1005,9 +1001,10 @@ template struct arg_mapper { } template > - struct formattable : bool_constant() || - (has_formatter::value && - !std::is_const::value)> {}; + struct formattable + : bool_constant() || + (std::is_constructible>::value && + !std::is_const::value)> {}; template ::value)> FMT_MAP_API auto do_map(T& val) -> T& { @@ -1790,8 +1787,7 @@ struct compile_string {}; template FMT_VISIBILITY("hidden") // Suppress an ld warning on macOS (#3769). FMT_CONSTEXPR auto invoke_parse(parse_context& ctx) -> const Char* { - using mapper = arg_mapper>; - using mapped_type = remove_cvref_t()))>; + using mapped_type = remove_cvref_t>; #if defined(__cpp_if_constexpr) if constexpr (std::is_default_constructible>()) return formatter().parse(ctx); diff --git a/include/fmt/ranges.h b/include/fmt/ranges.h index cbc12b2a6072..56340e1b50bc 100644 --- a/include/fmt/ranges.h +++ b/include/fmt/ranges.h @@ -358,16 +358,21 @@ template struct is_range { }; namespace detail { + +template +using has_formatter = std::is_constructible>; + template struct range_mapper { using mapper = arg_mapper; + using char_type = typename Context::char_type; template , Context>::value)> + FMT_ENABLE_IF(has_formatter, char_type>::value)> static auto map(T&& value) -> T&& { return static_cast(value); } template , Context>::value)> + FMT_ENABLE_IF(!has_formatter, char_type>::value)> static auto map(T&& value) -> decltype(mapper::map(static_cast(value))) { return mapper::map(static_cast(value)); } diff --git a/test/base-test.cc b/test/base-test.cc index 357185d45f0d..3d5a74ab83e1 100644 --- a/test/base-test.cc +++ b/test/base-test.cc @@ -604,15 +604,6 @@ template <> struct formatter { }; FMT_END_NAMESPACE -TEST(base_test, has_formatter) { - using fmt::has_formatter; - using context = fmt::format_context; - static_assert(has_formatter::value, ""); - static_assert(!has_formatter::value, ""); - static_assert(!has_formatter::value, - ""); -} - struct const_formattable {}; struct nonconst_formattable {}; diff --git a/test/format-test.cc b/test/format-test.cc index 75baa290cce7..6491449ff052 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -2022,8 +2022,8 @@ TEST(format_test, named_arg_udl) { TEST(format_test, enum) { EXPECT_EQ(fmt::format("{}", foo), "0"); } TEST(format_test, formatter_not_specialized) { - static_assert(!fmt::has_formatter, - fmt::format_context>::value, + static_assert(!fmt::is_formattable, + fmt::format_context>::value, ""); } diff --git a/test/ranges-test.cc b/test/ranges-test.cc index 40d545b146ab..0b6c32c16145 100644 --- a/test/ranges-test.cc +++ b/test/ranges-test.cc @@ -363,8 +363,7 @@ TEST(ranges_test, enum_range) { #if !FMT_MSC_VERSION TEST(ranges_test, unformattable_range) { - EXPECT_FALSE((fmt::has_formatter, - fmt::format_context>::value)); + EXPECT_FALSE((fmt::is_formattable, char>::value)); } #endif