mirror of
https://github.com/fmtlib/fmt.git
synced 2025-02-14 09:39:51 +00:00
Deprecate convert_to_int
This commit is contained in:
parent
40779749ac
commit
cb4c59495e
@ -483,17 +483,19 @@ template <typename Context> class basic_format_args;
|
||||
// A formatter for objects of type T.
|
||||
template <typename T, typename Char = char, typename Enable = void>
|
||||
struct formatter {
|
||||
// A deleted default constructor indicates a disabled formatter.
|
||||
formatter() = delete;
|
||||
};
|
||||
|
||||
template <typename T, typename Char, typename Enable = void>
|
||||
struct convert_to_int : bool_constant<!std::is_arithmetic<T>::value &&
|
||||
std::is_convertible<T, int>::value> {};
|
||||
struct FMT_DEPRECATED convert_to_int
|
||||
: bool_constant<!std::is_arithmetic<T>::value &&
|
||||
std::is_convertible<T, int>::value> {};
|
||||
|
||||
namespace internal {
|
||||
|
||||
// Specifies if T has an enabled formatter specialization. The type can be
|
||||
// formattable even if it doesn't have a formatter e.g. via conversion.
|
||||
// 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>>;
|
||||
@ -603,16 +605,16 @@ inline Container& get_container(std::back_insert_iterator<Container> it) {
|
||||
return *accessor(it).container;
|
||||
}
|
||||
|
||||
template <typename T> struct no_formatter_error : std::false_type {};
|
||||
|
||||
template <typename T, typename Char = char, typename Enable = void>
|
||||
struct fallback_formatter {
|
||||
static_assert(
|
||||
no_formatter_error<T>::value,
|
||||
"don't know how to format the type, include fmt/ostream.h if it provides "
|
||||
"an operator<< that should be used");
|
||||
fallback_formatter() = delete;
|
||||
};
|
||||
|
||||
// Specifies if T has an enabled fallback_formatter specialization.
|
||||
template <typename T, typename Context>
|
||||
using has_fallback_formatter =
|
||||
std::is_constructible<fallback_formatter<T, typename Context::char_type>>;
|
||||
|
||||
template <typename Char> struct named_arg_base;
|
||||
|
||||
template <typename T, typename Char> struct named_arg;
|
||||
@ -658,8 +660,6 @@ FMT_TYPE_CONSTANT(const Char*, cstring_type);
|
||||
FMT_TYPE_CONSTANT(basic_string_view<Char>, string_type);
|
||||
FMT_TYPE_CONSTANT(const void*, pointer_type);
|
||||
|
||||
#undef FMT_TYPE_CONSTANT
|
||||
|
||||
FMT_CONSTEXPR bool is_integral(type t) {
|
||||
FMT_ASSERT(t != internal::named_arg_type, "invalid argument type");
|
||||
return t > internal::none_type && t <= internal::last_integer_type;
|
||||
@ -795,6 +795,7 @@ FMT_MAKE_VALUE_SAME(long_long_type, long long)
|
||||
FMT_MAKE_VALUE_SAME(ulong_long_type, unsigned long long)
|
||||
FMT_MAKE_VALUE(int_type, signed char, int)
|
||||
FMT_MAKE_VALUE(uint_type, unsigned char, unsigned)
|
||||
FMT_MAKE_VALUE(char_type, char, int)
|
||||
|
||||
// This doesn't use FMT_MAKE_VALUE because of ambiguity in gcc 4.4.
|
||||
template <typename C, typename Char,
|
||||
@ -803,10 +804,11 @@ FMT_CONSTEXPR init<C, int, char_type> make_value(Char val) {
|
||||
return {val};
|
||||
}
|
||||
|
||||
template <typename C,
|
||||
FMT_ENABLE_IF(!std::is_same<typename C::char_type, char>::value)>
|
||||
FMT_CONSTEXPR init<C, int, char_type> make_value(char val) {
|
||||
return val;
|
||||
template <typename C, typename T,
|
||||
FMT_ENABLE_IF(is_char<T>::value && !std::is_same<T, char>::value &&
|
||||
!std::is_same<T, typename C::char_type>::value)>
|
||||
FMT_CONSTEXPR init<C, int, char_type> make_value(const T&) {
|
||||
static_assert(!sizeof(T), "mixing character types is disallowed");
|
||||
}
|
||||
|
||||
FMT_MAKE_VALUE(double_type, float, double)
|
||||
@ -855,8 +857,8 @@ void make_value(const T*) {
|
||||
}
|
||||
|
||||
template <typename C, typename T,
|
||||
FMT_ENABLE_IF(std::is_enum<T>::value&&
|
||||
convert_to_int<T, typename C::char_type>::value)>
|
||||
FMT_ENABLE_IF(std::is_enum<T>::value && !has_formatter<T, C>::value &&
|
||||
!has_fallback_formatter<T, C>::value)>
|
||||
inline init<C, int, int_type> make_value(const T& val) {
|
||||
return static_cast<int>(val);
|
||||
}
|
||||
@ -866,8 +868,9 @@ inline init<C, int, int_type> make_value(const T& val) {
|
||||
template <
|
||||
typename C, typename T, typename Char = typename C::char_type,
|
||||
typename U = typename std::remove_volatile<T>::type,
|
||||
FMT_ENABLE_IF(!convert_to_int<U, Char>::value &&
|
||||
!std::is_same<U, Char>::value &&
|
||||
FMT_ENABLE_IF(!std::is_same<U, Char>::value &&
|
||||
(!std::is_convertible<U, int>::value ||
|
||||
has_fallback_formatter<U, C>::value) &&
|
||||
!std::is_convertible<U, basic_string_view<Char>>::value &&
|
||||
!std::is_constructible<basic_string_view<Char>, U>::value &&
|
||||
!internal::is_string<U>::value)>
|
||||
|
@ -3035,7 +3035,7 @@ class format_int {
|
||||
std::string str() const { return std::string(str_, size()); }
|
||||
};
|
||||
|
||||
// formatter specializations for the core types corresponding to internal::type
|
||||
// A formatter specialization for the core types corresponding to internal::type
|
||||
// constants.
|
||||
template <typename T, typename Char>
|
||||
struct formatter<T, Char,
|
||||
@ -3131,8 +3131,6 @@ FMT_FORMAT_AS(Char*, const Char*);
|
||||
FMT_FORMAT_AS(std::basic_string<Char>, basic_string_view<Char>);
|
||||
FMT_FORMAT_AS(std::nullptr_t, const void*);
|
||||
|
||||
#undef FMT_FORMAT_AS
|
||||
|
||||
template <typename Char>
|
||||
struct formatter<void*, Char> : formatter<const void*, Char> {
|
||||
template <typename FormatContext>
|
||||
|
@ -109,14 +109,6 @@ struct fallback_formatter<T, Char,
|
||||
};
|
||||
} // namespace internal
|
||||
|
||||
// Disable conversion to int if T has an overloaded operator<< which is a free
|
||||
// function (not a member of std::ostream).
|
||||
template <typename T, typename Char>
|
||||
struct convert_to_int<T, Char,
|
||||
enable_if_t<internal::is_streamable<T, Char>::value>> {
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template <typename Char>
|
||||
void vprint(std::basic_ostream<Char>& os, basic_string_view<Char> format_str,
|
||||
basic_format_args<buffer_context<Char>> args) {
|
||||
|
@ -432,14 +432,29 @@ TEST(StringViewTest, Compare) {
|
||||
check_op<std::greater_equal>();
|
||||
}
|
||||
|
||||
enum basic_enum {};
|
||||
enum enum_with_underlying_type : char {};
|
||||
struct enabled_formatter {};
|
||||
struct disabled_formatter {};
|
||||
struct disabled_formatter_convertible {
|
||||
operator int() const { return 42; }
|
||||
};
|
||||
|
||||
TEST(CoreTest, ConvertToInt) {
|
||||
EXPECT_FALSE((fmt::convert_to_int<char, char>::value));
|
||||
EXPECT_FALSE((fmt::convert_to_int<const char*, char>::value));
|
||||
EXPECT_TRUE((fmt::convert_to_int<basic_enum, char>::value));
|
||||
EXPECT_TRUE((fmt::convert_to_int<enum_with_underlying_type, char>::value));
|
||||
FMT_BEGIN_NAMESPACE
|
||||
template <> struct formatter<enabled_formatter> {
|
||||
auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
|
||||
return ctx.begin();
|
||||
}
|
||||
auto format(enabled_formatter, format_context& ctx) -> decltype(ctx.out()) {
|
||||
return ctx.out();
|
||||
}
|
||||
};
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
TEST(CoreTest, HasFormatter) {
|
||||
using fmt::internal::has_formatter;
|
||||
using context = fmt::format_context;
|
||||
EXPECT_TRUE((has_formatter<enabled_formatter, context>::value));
|
||||
EXPECT_FALSE((has_formatter<disabled_formatter, context>::value));
|
||||
EXPECT_FALSE((has_formatter<disabled_formatter_convertible, context>::value));
|
||||
}
|
||||
|
||||
struct convertible_to_int {
|
||||
|
@ -1877,8 +1877,8 @@ enum TestEnum { A };
|
||||
TEST(FormatTest, Enum) { EXPECT_EQ("0", fmt::format("{}", A)); }
|
||||
|
||||
TEST(FormatTest, FormatterNotSpecialized) {
|
||||
EXPECT_FALSE((fmt::internal::has_formatter<
|
||||
fmt::formatter<TestEnum>, fmt::format_context>::value));
|
||||
EXPECT_FALSE((fmt::internal::has_formatter<fmt::formatter<TestEnum>,
|
||||
fmt::format_context>::value));
|
||||
}
|
||||
|
||||
#if FMT_HAS_FEATURE(cxx_strong_enums)
|
||||
|
@ -46,24 +46,22 @@ struct type_with_comma_op {};
|
||||
template <typename T> void operator,(type_with_comma_op, const T&);
|
||||
template <typename T> type_with_comma_op operator<<(T&, const Date&);
|
||||
|
||||
enum TestEnum {};
|
||||
static std::ostream& operator<<(std::ostream& os, TestEnum) {
|
||||
return os << "TestEnum";
|
||||
enum streamable_enum {};
|
||||
static std::ostream& operator<<(std::ostream& os, streamable_enum) {
|
||||
return os << "streamable_enum";
|
||||
}
|
||||
|
||||
static std::wostream& operator<<(std::wostream& os, TestEnum) {
|
||||
return os << L"TestEnum";
|
||||
static std::wostream& operator<<(std::wostream& os, streamable_enum) {
|
||||
return os << L"streamable_enum";
|
||||
}
|
||||
|
||||
enum TestEnum2 { A };
|
||||
enum unstreamable_enum {};
|
||||
|
||||
TEST(OStreamTest, Enum) {
|
||||
EXPECT_FALSE((fmt::convert_to_int<TestEnum, char>::value));
|
||||
EXPECT_EQ("TestEnum", fmt::format("{}", TestEnum()));
|
||||
EXPECT_EQ("0", fmt::format("{}", A));
|
||||
EXPECT_FALSE((fmt::convert_to_int<TestEnum, wchar_t>::value));
|
||||
EXPECT_EQ(L"TestEnum", fmt::format(L"{}", TestEnum()));
|
||||
EXPECT_EQ(L"0", fmt::format(L"{}", A));
|
||||
EXPECT_EQ("streamable_enum", fmt::format("{}", streamable_enum()));
|
||||
EXPECT_EQ("0", fmt::format("{}", unstreamable_enum()));
|
||||
EXPECT_EQ(L"streamable_enum", fmt::format(L"{}", streamable_enum()));
|
||||
EXPECT_EQ(L"0", fmt::format(L"{}", unstreamable_enum()));
|
||||
}
|
||||
|
||||
typedef fmt::back_insert_range<fmt::internal::buffer<char>> range;
|
||||
@ -81,8 +79,8 @@ TEST(OStreamTest, CustomArg) {
|
||||
fmt::format_specs spec;
|
||||
test_arg_formatter af(ctx, spec);
|
||||
fmt::visit_format_arg(
|
||||
af, fmt::internal::make_arg<fmt::format_context>(TestEnum()));
|
||||
EXPECT_EQ("TestEnum", std::string(buffer.data(), buffer.size()));
|
||||
af, fmt::internal::make_arg<fmt::format_context>(streamable_enum()));
|
||||
EXPECT_EQ("streamable_enum", std::string(buffer.data(), buffer.size()));
|
||||
}
|
||||
|
||||
TEST(OStreamTest, Format) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user