mirror of
https://github.com/fmtlib/fmt.git
synced 2025-07-30 10:47:35 +02:00
Cleanup base API
This commit is contained in:
@ -529,6 +529,8 @@ inline FMT_CONSTEXPR20 auto get_container(OutputIt it) ->
|
|||||||
}
|
}
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
|
FMT_BEGIN_EXPORT
|
||||||
|
|
||||||
// Checks whether T is a container with contiguous storage.
|
// Checks whether T is a container with contiguous storage.
|
||||||
template <typename T> struct is_contiguous : std::false_type {};
|
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
|
* compiled with a different `-std` option than the client code (which is not
|
||||||
* recommended).
|
* recommended).
|
||||||
*/
|
*/
|
||||||
FMT_EXPORT
|
|
||||||
template <typename Char> class basic_string_view {
|
template <typename Char> class basic_string_view {
|
||||||
private:
|
private:
|
||||||
const Char* data_;
|
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.
|
/// Specifies if `T` is a character type. Can be specialized by users.
|
||||||
template <typename T> struct is_char : std::false_type {};
|
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,
|
conditional_t<std::is_same<Char, char>::value, context,
|
||||||
generic_context<basic_appender<Char>, Char>>;
|
generic_context<basic_appender<Char>, Char>>;
|
||||||
|
|
||||||
FMT_EXPORT template <typename Context> class basic_format_arg;
|
template <typename Context> class basic_format_arg;
|
||||||
FMT_EXPORT template <typename Context> class basic_format_args;
|
template <typename Context> class basic_format_args;
|
||||||
FMT_EXPORT template <typename Context> class dynamic_format_arg_store;
|
template <typename Context> class dynamic_format_arg_store;
|
||||||
|
|
||||||
// A separate type would result in shorter symbols but break ABI compatibility
|
// A separate type would result in shorter symbols but break ABI compatibility
|
||||||
// between clang and gcc on ARM (#1919).
|
// between clang and gcc on ARM (#1919).
|
||||||
using format_args = basic_format_args<context>;
|
using format_args = basic_format_args<context>;
|
||||||
|
|
||||||
// A formatter for objects of type T.
|
// A formatter for objects of type T.
|
||||||
FMT_EXPORT
|
|
||||||
template <typename T, typename Char = char, typename Enable = void>
|
template <typename T, typename Char = char, typename Enable = void>
|
||||||
struct formatter {
|
struct formatter {
|
||||||
// A deleted default constructor indicates a disabled formatter.
|
// A deleted default constructor indicates a disabled formatter.
|
||||||
formatter() = delete;
|
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.
|
// 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.
|
// It is a template to avoid undesirable implicit conversions to std::byte.
|
||||||
#ifdef __cpp_lib_byte
|
#ifdef __cpp_lib_byte
|
||||||
@ -688,6 +682,8 @@ inline auto format_as(T b) -> unsigned char {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
FMT_END_EXPORT
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
// Constructs fmt::basic_string_view<Char> from types implicitly convertible
|
// 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>>
|
template <typename T, typename U = remove_const_t<T>>
|
||||||
struct formattable : bool_constant<has_const_formatter<U, Context>() ||
|
struct formattable
|
||||||
(has_formatter<U, Context>::value &&
|
: bool_constant<has_const_formatter<U, Context>() ||
|
||||||
!std::is_const<T>::value)> {};
|
(std::is_constructible<formatter<U, char_type>>::value &&
|
||||||
|
!std::is_const<T>::value)> {};
|
||||||
|
|
||||||
template <typename T, FMT_ENABLE_IF(formattable<T>::value)>
|
template <typename T, FMT_ENABLE_IF(formattable<T>::value)>
|
||||||
FMT_MAP_API auto do_map(T& val) -> T& {
|
FMT_MAP_API auto do_map(T& val) -> T& {
|
||||||
@ -1790,8 +1787,7 @@ struct compile_string {};
|
|||||||
template <typename T, typename Char>
|
template <typename T, typename Char>
|
||||||
FMT_VISIBILITY("hidden") // Suppress an ld warning on macOS (#3769).
|
FMT_VISIBILITY("hidden") // Suppress an ld warning on macOS (#3769).
|
||||||
FMT_CONSTEXPR auto invoke_parse(parse_context<Char>& ctx) -> const Char* {
|
FMT_CONSTEXPR auto invoke_parse(parse_context<Char>& ctx) -> const Char* {
|
||||||
using mapper = arg_mapper<buffered_context<Char>>;
|
using mapped_type = remove_cvref_t<mapped_t<T, Char>>;
|
||||||
using mapped_type = remove_cvref_t<decltype(mapper::map(std::declval<T&>()))>;
|
|
||||||
#if defined(__cpp_if_constexpr)
|
#if defined(__cpp_if_constexpr)
|
||||||
if constexpr (std::is_default_constructible<formatter<mapped_type, Char>>())
|
if constexpr (std::is_default_constructible<formatter<mapped_type, Char>>())
|
||||||
return formatter<mapped_type, Char>().parse(ctx);
|
return formatter<mapped_type, Char>().parse(ctx);
|
||||||
|
@ -358,16 +358,21 @@ template <typename T, typename Char> struct is_range {
|
|||||||
};
|
};
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
|
template <typename T, typename Char>
|
||||||
|
using has_formatter = std::is_constructible<formatter<T, Char>>;
|
||||||
|
|
||||||
template <typename Context> struct range_mapper {
|
template <typename Context> struct range_mapper {
|
||||||
using mapper = arg_mapper<Context>;
|
using mapper = arg_mapper<Context>;
|
||||||
|
using char_type = typename Context::char_type;
|
||||||
|
|
||||||
template <typename T,
|
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&& {
|
static auto map(T&& value) -> T&& {
|
||||||
return static_cast<T&&>(value);
|
return static_cast<T&&>(value);
|
||||||
}
|
}
|
||||||
template <typename T,
|
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))) {
|
static auto map(T&& value) -> decltype(mapper::map(static_cast<T&&>(value))) {
|
||||||
return mapper::map(static_cast<T&&>(value));
|
return mapper::map(static_cast<T&&>(value));
|
||||||
}
|
}
|
||||||
|
@ -604,15 +604,6 @@ template <> struct formatter<enabled_ptr_formatter*> {
|
|||||||
};
|
};
|
||||||
FMT_END_NAMESPACE
|
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 const_formattable {};
|
||||||
struct nonconst_formattable {};
|
struct nonconst_formattable {};
|
||||||
|
|
||||||
|
@ -2022,8 +2022,8 @@ TEST(format_test, named_arg_udl) {
|
|||||||
TEST(format_test, enum) { EXPECT_EQ(fmt::format("{}", foo), "0"); }
|
TEST(format_test, enum) { EXPECT_EQ(fmt::format("{}", foo), "0"); }
|
||||||
|
|
||||||
TEST(format_test, formatter_not_specialized) {
|
TEST(format_test, formatter_not_specialized) {
|
||||||
static_assert(!fmt::has_formatter<fmt::formatter<test_enum>,
|
static_assert(!fmt::is_formattable<fmt::formatter<test_enum>,
|
||||||
fmt::format_context>::value,
|
fmt::format_context>::value,
|
||||||
"");
|
"");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,8 +363,7 @@ TEST(ranges_test, enum_range) {
|
|||||||
|
|
||||||
#if !FMT_MSC_VERSION
|
#if !FMT_MSC_VERSION
|
||||||
TEST(ranges_test, unformattable_range) {
|
TEST(ranges_test, unformattable_range) {
|
||||||
EXPECT_FALSE((fmt::has_formatter<std::vector<unformattable>,
|
EXPECT_FALSE((fmt::is_formattable<std::vector<unformattable>, char>::value));
|
||||||
fmt::format_context>::value));
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user