Cleanup base API

This commit is contained in:
Victor Zverovich 2024-09-01 19:35:00 -07:00
parent 9ef160d309
commit 60740b7c24
5 changed files with 23 additions and 32 deletions

View File

@ -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 <typename T> struct is_contiguous : std::false_type {};
@ -539,7 +541,6 @@ template <typename T> struct is_contiguous : std::false_type {};
* compiled with a different `-std` option than the client code (which is not
* recommended).
*/
FMT_EXPORT
template <typename Char> class basic_string_view {
private:
const Char* data_;
@ -633,7 +634,7 @@ template <typename Char> class basic_string_view {
}
};
FMT_EXPORT using string_view = basic_string_view<char>;
using string_view = basic_string_view<char>;
/// Specifies if `T` is a character type. Can be specialized by users.
template <typename T> struct is_char : std::false_type {};
@ -657,28 +658,21 @@ using buffered_context =
conditional_t<std::is_same<Char, char>::value, context,
generic_context<basic_appender<Char>, Char>>;
FMT_EXPORT template <typename Context> class basic_format_arg;
FMT_EXPORT template <typename Context> class basic_format_args;
FMT_EXPORT template <typename Context> class dynamic_format_arg_store;
template <typename Context> class basic_format_arg;
template <typename Context> class basic_format_args;
template <typename Context> 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<context>;
// A formatter for objects of type T.
FMT_EXPORT
template <typename T, typename Char = char, typename Enable = void>
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 <typename T, typename Context>
using has_formatter =
std::is_constructible<typename Context::template formatter_type<T>>;
// 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<Char> from types implicitly convertible
@ -1005,9 +1001,10 @@ template <typename Context> struct arg_mapper {
}
template <typename T, typename U = remove_const_t<T>>
struct formattable : bool_constant<has_const_formatter<U, Context>() ||
(has_formatter<U, Context>::value &&
!std::is_const<T>::value)> {};
struct formattable
: bool_constant<has_const_formatter<U, Context>() ||
(std::is_constructible<formatter<U, char_type>>::value &&
!std::is_const<T>::value)> {};
template <typename T, FMT_ENABLE_IF(formattable<T>::value)>
FMT_MAP_API auto do_map(T& val) -> T& {
@ -1790,8 +1787,7 @@ struct compile_string {};
template <typename T, typename Char>
FMT_VISIBILITY("hidden") // Suppress an ld warning on macOS (#3769).
FMT_CONSTEXPR auto invoke_parse(parse_context<Char>& ctx) -> const Char* {
using mapper = arg_mapper<buffered_context<Char>>;
using mapped_type = remove_cvref_t<decltype(mapper::map(std::declval<T&>()))>;
using mapped_type = remove_cvref_t<mapped_t<T, Char>>;
#if defined(__cpp_if_constexpr)
if constexpr (std::is_default_constructible<formatter<mapped_type, Char>>())
return formatter<mapped_type, Char>().parse(ctx);

View File

@ -358,16 +358,21 @@ template <typename T, typename Char> struct is_range {
};
namespace detail {
template <typename T, typename Char>
using has_formatter = std::is_constructible<formatter<T, Char>>;
template <typename Context> struct range_mapper {
using mapper = arg_mapper<Context>;
using char_type = typename Context::char_type;
template <typename T,
FMT_ENABLE_IF(has_formatter<remove_cvref_t<T>, Context>::value)>
FMT_ENABLE_IF(has_formatter<remove_cvref_t<T>, char_type>::value)>
static auto map(T&& value) -> T&& {
return static_cast<T&&>(value);
}
template <typename T,
FMT_ENABLE_IF(!has_formatter<remove_cvref_t<T>, Context>::value)>
FMT_ENABLE_IF(!has_formatter<remove_cvref_t<T>, char_type>::value)>
static auto map(T&& value) -> decltype(mapper::map(static_cast<T&&>(value))) {
return mapper::map(static_cast<T&&>(value));
}

View File

@ -604,15 +604,6 @@ template <> struct formatter<enabled_ptr_formatter*> {
};
FMT_END_NAMESPACE
TEST(base_test, has_formatter) {
using fmt::has_formatter;
using context = fmt::format_context;
static_assert(has_formatter<enabled_formatter, context>::value, "");
static_assert(!has_formatter<disabled_formatter, context>::value, "");
static_assert(!has_formatter<disabled_formatter_convertible, context>::value,
"");
}
struct const_formattable {};
struct nonconst_formattable {};

View File

@ -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::formatter<test_enum>,
fmt::format_context>::value,
static_assert(!fmt::is_formattable<fmt::formatter<test_enum>,
fmt::format_context>::value,
"");
}

View File

@ -363,8 +363,7 @@ TEST(ranges_test, enum_range) {
#if !FMT_MSC_VERSION
TEST(ranges_test, unformattable_range) {
EXPECT_FALSE((fmt::has_formatter<std::vector<unformattable>,
fmt::format_context>::value));
EXPECT_FALSE((fmt::is_formattable<std::vector<unformattable>, char>::value));
}
#endif