thou shall not pass
This commit is contained in:
parent
19cac63fe4
commit
75f3115c94
@ -1146,6 +1146,9 @@ constexpr bool is_arithmetic_type(type t) {
|
||||
struct unformattable {};
|
||||
struct unformattable_char : unformattable {};
|
||||
struct unformattable_const : unformattable {};
|
||||
struct unformattable_function_pointer : unformattable {};
|
||||
struct unformattable_member_function_pointer : unformattable {};
|
||||
struct unformattable_member_object_pointer : unformattable {};
|
||||
struct unformattable_pointer : unformattable {};
|
||||
|
||||
template <typename Char> struct string_value {
|
||||
@ -1228,6 +1231,9 @@ template <typename Context> class value {
|
||||
value(unformattable_char);
|
||||
value(unformattable_const);
|
||||
value(unformattable_pointer);
|
||||
value(unformattable_function_pointer);
|
||||
value(unformattable_member_function_pointer);
|
||||
value(unformattable_member_object_pointer);
|
||||
|
||||
private:
|
||||
// Formats an argument of a custom type, such as a user-defined class.
|
||||
@ -1368,11 +1374,32 @@ template <typename Context> struct arg_mapper {
|
||||
return val;
|
||||
}
|
||||
|
||||
template <typename T,
|
||||
FMT_ENABLE_IF(std::is_function<typename std::remove_pointer<
|
||||
remove_cvref_t<T>>::type>::value)>
|
||||
FMT_CONSTEXPR auto map(const T&) -> unformattable_function_pointer {
|
||||
return {};
|
||||
}
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(std::is_member_object_pointer<T>::value)>
|
||||
FMT_CONSTEXPR auto map(const T&) -> unformattable_member_object_pointer {
|
||||
return {};
|
||||
}
|
||||
|
||||
template <typename T,
|
||||
FMT_ENABLE_IF(std::is_member_function_pointer<T>::value)>
|
||||
FMT_CONSTEXPR auto map(const T&) -> unformattable_member_function_pointer {
|
||||
return {};
|
||||
}
|
||||
|
||||
// We use SFINAE instead of a const T* parameter to avoid conflicting with
|
||||
// the C array overload.
|
||||
|
||||
template <
|
||||
typename T,
|
||||
FMT_ENABLE_IF(std::is_convertible<const T&, const void*>::value &&
|
||||
FMT_ENABLE_IF(!std::is_function<typename std::remove_pointer<
|
||||
remove_cvref_t<T>>::type>::value &&
|
||||
std::is_convertible<const T&, const void*>::value &&
|
||||
!std::is_convertible<const T&, const char_type*>::value)>
|
||||
FMT_CONSTEXPR auto map(const T&) -> unformattable_pointer {
|
||||
return {};
|
||||
@ -1677,6 +1704,27 @@ FMT_CONSTEXPR FMT_INLINE auto make_arg(T&& val) -> value<Context> {
|
||||
static_assert(formattable_pointer,
|
||||
"Formatting of non-void pointers is disallowed.");
|
||||
|
||||
// Formatting of function pointers is disallowed.
|
||||
constexpr bool formattable_function_pointer =
|
||||
!std::is_same<decltype(arg),
|
||||
const unformattable_function_pointer&>::value;
|
||||
static_assert(formattable_function_pointer,
|
||||
"Formatting of function pointers is disallowed.");
|
||||
|
||||
// Formatting of member function pointers is disallowed.
|
||||
constexpr bool formattable_member_function_pointer =
|
||||
!std::is_same<decltype(arg),
|
||||
const unformattable_member_function_pointer&>::value;
|
||||
static_assert(formattable_member_function_pointer,
|
||||
"Formatting of member function pointers is disallowed.");
|
||||
|
||||
// Formatting of member object pointers is disallowed.
|
||||
constexpr bool formattable_member_object_pointer =
|
||||
!std::is_same<decltype(arg),
|
||||
const unformattable_member_object_pointer&>::value;
|
||||
static_assert(formattable_member_object_pointer,
|
||||
"Formatting of member object pointers is disallowed.");
|
||||
|
||||
constexpr bool formattable =
|
||||
!std::is_same<decltype(arg), const unformattable&>::value;
|
||||
static_assert(
|
||||
|
||||
@ -67,6 +67,12 @@ expect_compile_error("
|
||||
fmt::format(\"{}\", S());
|
||||
")
|
||||
|
||||
# Formatting a function
|
||||
expect_compile_error("
|
||||
void (*f)();
|
||||
fmt::format(\"{}\", f);
|
||||
")
|
||||
|
||||
# Make sure that compiler features detected in the header
|
||||
# match the features detected in CMake.
|
||||
if (SUPPORTS_USER_DEFINED_LITERALS)
|
||||
|
||||
@ -770,6 +770,13 @@ TEST(core_test, is_formattable) {
|
||||
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, "");
|
||||
|
||||
static_assert(!fmt::is_formattable<void (*)()>::value, "");
|
||||
|
||||
struct S;
|
||||
|
||||
static_assert(!fmt::is_formattable<int(S::*)>::value, "");
|
||||
static_assert(!fmt::is_formattable<int (S::*)()>::value, "");
|
||||
}
|
||||
|
||||
TEST(core_test, format) { EXPECT_EQ(fmt::format("{}", 42), "42"); }
|
||||
|
||||
Loading…
Reference in New Issue
Block a user