mirror of
https://github.com/fmtlib/fmt.git
synced 2025-08-03 12:44:49 +02:00
Fix error reporting when mixing character types
This commit is contained in:
@@ -1128,6 +1128,7 @@ constexpr bool is_arithmetic_type(type t) {
|
|||||||
|
|
||||||
struct unformattable {};
|
struct unformattable {};
|
||||||
struct unformattable_pointer : unformattable {};
|
struct unformattable_pointer : unformattable {};
|
||||||
|
struct unformattable_char : unformattable {};
|
||||||
|
|
||||||
template <typename Char> struct string_value {
|
template <typename Char> struct string_value {
|
||||||
const Char* data;
|
const Char* data;
|
||||||
@@ -1207,6 +1208,7 @@ template <typename Context> class value {
|
|||||||
}
|
}
|
||||||
value(unformattable);
|
value(unformattable);
|
||||||
value(unformattable_pointer);
|
value(unformattable_pointer);
|
||||||
|
value(unformattable_char);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Formats an argument of a custom type, such as a user-defined class.
|
// Formats an argument of a custom type, such as a user-defined class.
|
||||||
@@ -1260,13 +1262,16 @@ template <typename Context> struct arg_mapper {
|
|||||||
FMT_CONSTEXPR FMT_INLINE auto map(uint128_t val) -> uint128_t { return val; }
|
FMT_CONSTEXPR FMT_INLINE auto map(uint128_t val) -> uint128_t { return val; }
|
||||||
FMT_CONSTEXPR FMT_INLINE auto map(bool val) -> bool { return val; }
|
FMT_CONSTEXPR FMT_INLINE auto map(bool val) -> bool { return val; }
|
||||||
|
|
||||||
template <typename T, FMT_ENABLE_IF(is_char<T>::value)>
|
template <typename T, FMT_ENABLE_IF(std::is_same<T, char>::value ||
|
||||||
|
std::is_same<T, char_type>::value)>
|
||||||
FMT_CONSTEXPR FMT_INLINE auto map(T val) -> char_type {
|
FMT_CONSTEXPR FMT_INLINE auto map(T val) -> char_type {
|
||||||
static_assert(
|
|
||||||
std::is_same<T, char>::value || std::is_same<T, char_type>::value,
|
|
||||||
"mixing character types is disallowed");
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
template <typename T, FMT_ENABLE_IF(std::is_same<T, wchar_t>::value &&
|
||||||
|
!std::is_same<wchar_t, char_type>::value)>
|
||||||
|
FMT_CONSTEXPR FMT_INLINE auto map(T) -> unformattable_char {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
FMT_CONSTEXPR FMT_INLINE auto map(float val) -> float { return val; }
|
FMT_CONSTEXPR FMT_INLINE auto map(float val) -> float { return val; }
|
||||||
FMT_CONSTEXPR FMT_INLINE auto map(double val) -> double { return val; }
|
FMT_CONSTEXPR FMT_INLINE auto map(double val) -> double { return val; }
|
||||||
@@ -1281,13 +1286,18 @@ template <typename Context> struct arg_mapper {
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
template <typename T,
|
template <typename T,
|
||||||
FMT_ENABLE_IF(is_string<T>::value && !std::is_pointer<T>::value)>
|
FMT_ENABLE_IF(is_string<T>::value && !std::is_pointer<T>::value &&
|
||||||
|
std::is_same<char_type, char_t<T>>::value)>
|
||||||
FMT_CONSTEXPR FMT_INLINE auto map(const T& val)
|
FMT_CONSTEXPR FMT_INLINE auto map(const T& val)
|
||||||
-> basic_string_view<char_type> {
|
-> basic_string_view<char_type> {
|
||||||
static_assert(std::is_same<char_type, char_t<T>>::value,
|
|
||||||
"mixing character types is disallowed");
|
|
||||||
return to_string_view(val);
|
return to_string_view(val);
|
||||||
}
|
}
|
||||||
|
template <typename T,
|
||||||
|
FMT_ENABLE_IF(is_string<T>::value && !std::is_pointer<T>::value &&
|
||||||
|
!std::is_same<char_type, char_t<T>>::value)>
|
||||||
|
FMT_CONSTEXPR FMT_INLINE auto map(const T&) -> unformattable_char {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
template <typename T,
|
template <typename T,
|
||||||
FMT_ENABLE_IF(
|
FMT_ENABLE_IF(
|
||||||
std::is_constructible<basic_string_view<char_type>, T>::value &&
|
std::is_constructible<basic_string_view<char_type>, T>::value &&
|
||||||
@@ -1308,21 +1318,21 @@ template <typename Context> struct arg_mapper {
|
|||||||
-> basic_string_view<char_type> {
|
-> basic_string_view<char_type> {
|
||||||
return std_string_view<char_type>(val);
|
return std_string_view<char_type>(val);
|
||||||
}
|
}
|
||||||
FMT_CONSTEXPR FMT_INLINE auto map(const signed char* val) -> const char* {
|
FMT_CONSTEXPR FMT_INLINE auto map(const signed char* val)
|
||||||
static_assert(std::is_same<char_type, char>::value, "invalid string type");
|
-> decltype(this->map("")) {
|
||||||
return reinterpret_cast<const char*>(val);
|
return map(reinterpret_cast<const char*>(val));
|
||||||
}
|
}
|
||||||
FMT_CONSTEXPR FMT_INLINE auto map(const unsigned char* val) -> const char* {
|
FMT_CONSTEXPR FMT_INLINE auto map(const unsigned char* val)
|
||||||
static_assert(std::is_same<char_type, char>::value, "invalid string type");
|
-> decltype(this->map("")) {
|
||||||
return reinterpret_cast<const char*>(val);
|
return map(reinterpret_cast<const char*>(val));
|
||||||
}
|
}
|
||||||
FMT_CONSTEXPR FMT_INLINE auto map(signed char* val) -> const char* {
|
FMT_CONSTEXPR FMT_INLINE auto map(signed char* val)
|
||||||
const auto* const_val = val;
|
-> decltype(this->map("")) {
|
||||||
return map(const_val);
|
return map(reinterpret_cast<const char*>(val));
|
||||||
}
|
}
|
||||||
FMT_CONSTEXPR FMT_INLINE auto map(unsigned char* val) -> const char* {
|
FMT_CONSTEXPR FMT_INLINE auto map(unsigned char* val)
|
||||||
const auto* const_val = val;
|
-> decltype(this->map("")) {
|
||||||
return map(const_val);
|
return map(reinterpret_cast<const char*>(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
FMT_CONSTEXPR FMT_INLINE auto map(void* val) -> const void* { return val; }
|
FMT_CONSTEXPR FMT_INLINE auto map(void* val) -> const void* { return val; }
|
||||||
@@ -1609,6 +1619,11 @@ FMT_CONSTEXPR FMT_INLINE auto make_arg(T&& val) -> value<Context> {
|
|||||||
constexpr bool void_ptr =
|
constexpr bool void_ptr =
|
||||||
!std::is_same<decltype(arg), const unformattable_pointer&>::value;
|
!std::is_same<decltype(arg), const unformattable_pointer&>::value;
|
||||||
static_assert(void_ptr, "Formatting of non-void pointers is disallowed.");
|
static_assert(void_ptr, "Formatting of non-void pointers is disallowed.");
|
||||||
|
|
||||||
|
constexpr bool same_char =
|
||||||
|
!std::is_same<decltype(arg), const unformattable_char&>::value;
|
||||||
|
static_assert(same_char, "Mixing character types is disallowed.");
|
||||||
|
|
||||||
constexpr bool formattable =
|
constexpr bool formattable =
|
||||||
!std::is_same<decltype(arg), const unformattable&>::value;
|
!std::is_same<decltype(arg), const unformattable&>::value;
|
||||||
static_assert(
|
static_assert(
|
||||||
|
@@ -704,11 +704,23 @@ TEST(core_test, has_formatter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(core_test, is_formattable) {
|
TEST(core_test, is_formattable) {
|
||||||
|
static_assert(fmt::is_formattable<signed char*>::value, "");
|
||||||
|
static_assert(fmt::is_formattable<unsigned char*>::value, "");
|
||||||
|
static_assert(fmt::is_formattable<const signed char*>::value, "");
|
||||||
|
static_assert(fmt::is_formattable<const unsigned char*>::value, "");
|
||||||
|
static_assert(!fmt::is_formattable<wchar_t>::value, "");
|
||||||
static_assert(!fmt::is_formattable<const wchar_t*>::value, "");
|
static_assert(!fmt::is_formattable<const wchar_t*>::value, "");
|
||||||
static_assert(!fmt::is_formattable<const wchar_t[3]>::value, "");
|
static_assert(!fmt::is_formattable<const wchar_t[3]>::value, "");
|
||||||
|
static_assert(!fmt::is_formattable<fmt::basic_string_view<wchar_t>>::value,
|
||||||
|
"");
|
||||||
static_assert(fmt::is_formattable<enabled_formatter>::value, "");
|
static_assert(fmt::is_formattable<enabled_formatter>::value, "");
|
||||||
static_assert(!fmt::is_formattable<disabled_formatter>::value, "");
|
static_assert(!fmt::is_formattable<disabled_formatter>::value, "");
|
||||||
static_assert(fmt::is_formattable<disabled_formatter_convertible>::value, "");
|
static_assert(fmt::is_formattable<disabled_formatter_convertible>::value, "");
|
||||||
|
|
||||||
|
static_assert(!fmt::is_formattable<signed char*, wchar_t>::value, "");
|
||||||
|
static_assert(!fmt::is_formattable<unsigned char*, wchar_t>::value, "");
|
||||||
|
static_assert(!fmt::is_formattable<const signed char*, wchar_t>::value, "");
|
||||||
|
static_assert(!fmt::is_formattable<const unsigned char*, wchar_t>::value, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(core_test, format) { EXPECT_EQ(fmt::format("{}", 42), "42"); }
|
TEST(core_test, format) { EXPECT_EQ(fmt::format("{}", 42), "42"); }
|
||||||
|
Reference in New Issue
Block a user