Added formattable concept (#3974)

This commit is contained in:
Matthias Moulin 2024-05-26 16:47:56 +02:00 committed by GitHub
parent 1768bf9714
commit 1752d7fbbb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 84 additions and 0 deletions

View File

@ -149,6 +149,15 @@ import std;
# define FMT_USE_NONTYPE_TEMPLATE_ARGS 0
#endif
// Detect C++20 concepts
#ifdef FMT_USE_CONCEPTS
// Use the provided definition.
#elif defined(__cpp_concepts)
# define FMT_USE_CONCEPTS 1
#else
# define FMT_USE_CONCEPTS 0
#endif
// Check if exceptions are disabled.
#ifdef FMT_EXCEPTIONS
// Use the provided definition.
@ -2007,6 +2016,11 @@ using is_formattable = bool_constant<!std::is_base_of<
detail::unformattable, decltype(detail::arg_mapper<buffered_context<Char>>()
.map(std::declval<T&>()))>::value>;
#if FMT_USE_CONCEPTS
template <typename T, typename Char = char>
concept formattable = is_formattable<remove_reference_t<T>, Char>::value;
#endif
/**
\rst
Constructs an object that stores references to arguments and can be implicitly

View File

@ -687,6 +687,64 @@ TEST(core_test, is_formattable) {
static_assert(!fmt::is_formattable<unformattable_scoped_enum>::value, "");
}
#if FMT_USE_CONCEPTS
TEST(core_test, formattable) {
static_assert(fmt::formattable<char>);
static_assert(fmt::formattable<char&>);
static_assert(fmt::formattable<char&&>);
static_assert(fmt::formattable<const char>);
static_assert(fmt::formattable<const char&>);
static_assert(fmt::formattable<const char&&>);
static_assert(fmt::formattable<fmt::basic_string_view<char>>);
static_assert(fmt::formattable<fmt::basic_string_view<char>&>);
static_assert(fmt::formattable<fmt::basic_string_view<char>&&>);
static_assert(fmt::formattable<const fmt::basic_string_view<char>>);
static_assert(fmt::formattable<const fmt::basic_string_view<char>&>);
static_assert(fmt::formattable<const fmt::basic_string_view<char>&&>);
static_assert(!fmt::formattable<wchar_t>);
# ifdef __cpp_char8_t
static_assert(!fmt::formattable<char8_t>);
# endif
static_assert(!fmt::formattable<char16_t>);
static_assert(!fmt::formattable<char32_t>);
static_assert(!fmt::formattable<signed char*>);
static_assert(!fmt::formattable<unsigned char*>);
static_assert(!fmt::formattable<const signed char*>);
static_assert(!fmt::formattable<const unsigned char*>);
static_assert(!fmt::formattable<const wchar_t*>);
static_assert(!fmt::formattable<const wchar_t[3]>);
static_assert(!fmt::formattable<fmt::basic_string_view<wchar_t>>);
static_assert(fmt::formattable<enabled_formatter>);
static_assert(!fmt::formattable<enabled_ptr_formatter*>);
static_assert(!fmt::formattable<disabled_formatter>);
static_assert(!fmt::formattable<disabled_formatter_convertible>);
static_assert(fmt::formattable<const_formattable&>);
static_assert(fmt::formattable<const const_formattable&>);
static_assert(fmt::formattable<nonconst_formattable&>);
# if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1910
static_assert(!fmt::formattable<const nonconst_formattable&>);
# endif
static_assert(!fmt::formattable<convertible_to_pointer>);
const auto f = convertible_to_pointer_formattable();
auto str = std::string();
fmt::format_to(std::back_inserter(str), "{}", f);
EXPECT_EQ(str, "test");
static_assert(!fmt::formattable<void (*)()>);
struct s;
static_assert(!fmt::formattable<int(s::*)>);
static_assert(!fmt::formattable<int (s::*)()>);
static_assert(!fmt::formattable<unformattable_scoped_enum>);
static_assert(!fmt::formattable<unformattable_scoped_enum>);
}
#endif
TEST(core_test, format_to) {
auto s = std::string();
fmt::format_to(std::back_inserter(s), "{}", 42);
@ -757,6 +815,9 @@ struct implicitly_convertible_to_string_view {
TEST(core_test, no_implicit_conversion_to_string_view) {
EXPECT_FALSE(
fmt::is_formattable<implicitly_convertible_to_string_view>::value);
#if FMT_USE_CONCEPTS
static_assert(!fmt::formattable<implicitly_convertible_to_string_view>);
#endif
}
#ifdef FMT_USE_STRING_VIEW
@ -767,6 +828,9 @@ struct implicitly_convertible_to_std_string_view {
TEST(core_test, no_implicit_conversion_to_std_string_view) {
EXPECT_FALSE(
fmt::is_formattable<implicitly_convertible_to_std_string_view>::value);
# if FMT_USE_CONCEPTS
static_assert(!fmt::formattable<implicitly_convertible_to_std_string_view>);
# endif
}
#endif
@ -781,6 +845,9 @@ TEST(core_test, format_explicitly_convertible_to_string_view) {
// default because it may introduce ODR violations.
static_assert(
!fmt::is_formattable<explicitly_convertible_to_string_view>::value, "");
# if FMT_USE_CONCEPTS
static_assert(!fmt::formattable<explicitly_convertible_to_string_view>);
# endif
}
# ifdef FMT_USE_STRING_VIEW
@ -794,6 +861,9 @@ TEST(core_test, format_explicitly_convertible_to_std_string_view) {
static_assert(
!fmt::is_formattable<explicitly_convertible_to_std_string_view>::value,
"");
# if FMT_USE_CONCEPTS
static_assert(!fmt::formattable<explicitly_convertible_to_std_string_view>);
# endif
}
# endif
#endif