From 1752d7fbbbeb5ae2fb30bad5f370a03c3f82e7c7 Mon Sep 17 00:00:00 2001 From: Matthias Moulin Date: Sun, 26 May 2024 16:47:56 +0200 Subject: [PATCH] Added formattable concept (#3974) --- include/fmt/base.h | 14 ++++++++++ test/base-test.cc | 70 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/include/fmt/base.h b/include/fmt/base.h index c8402895..5be5c062 100644 --- a/include/fmt/base.h +++ b/include/fmt/base.h @@ -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>() .map(std::declval()))>::value>; +#if FMT_USE_CONCEPTS +template +concept formattable = is_formattable, Char>::value; +#endif + /** \rst Constructs an object that stores references to arguments and can be implicitly diff --git a/test/base-test.cc b/test/base-test.cc index b8ec60d8..0c95e621 100644 --- a/test/base-test.cc +++ b/test/base-test.cc @@ -687,6 +687,64 @@ TEST(core_test, is_formattable) { static_assert(!fmt::is_formattable::value, ""); } +#if FMT_USE_CONCEPTS +TEST(core_test, formattable) { + static_assert(fmt::formattable); + static_assert(fmt::formattable); + static_assert(fmt::formattable); + static_assert(fmt::formattable); + static_assert(fmt::formattable); + static_assert(fmt::formattable); + + static_assert(fmt::formattable>); + static_assert(fmt::formattable&>); + static_assert(fmt::formattable&&>); + static_assert(fmt::formattable>); + static_assert(fmt::formattable&>); + static_assert(fmt::formattable&&>); + + static_assert(!fmt::formattable); +# ifdef __cpp_char8_t + static_assert(!fmt::formattable); +# endif + static_assert(!fmt::formattable); + static_assert(!fmt::formattable); + static_assert(!fmt::formattable); + static_assert(!fmt::formattable); + static_assert(!fmt::formattable); + static_assert(!fmt::formattable); + static_assert(!fmt::formattable); + static_assert(!fmt::formattable); + static_assert(!fmt::formattable>); + static_assert(fmt::formattable); + static_assert(!fmt::formattable); + static_assert(!fmt::formattable); + static_assert(!fmt::formattable); + + static_assert(fmt::formattable); + static_assert(fmt::formattable); + + static_assert(fmt::formattable); +# if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1910 + static_assert(!fmt::formattable); +# endif + + static_assert(!fmt::formattable); + 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); + + struct s; + static_assert(!fmt::formattable); + static_assert(!fmt::formattable); + static_assert(!fmt::formattable); + static_assert(!fmt::formattable); +} +#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::value); +#if FMT_USE_CONCEPTS + static_assert(!fmt::formattable); +#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::value); +# if FMT_USE_CONCEPTS + static_assert(!fmt::formattable); +# 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::value, ""); +# if FMT_USE_CONCEPTS + static_assert(!fmt::formattable); +# 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::value, ""); +# if FMT_USE_CONCEPTS + static_assert(!fmt::formattable); +# endif } # endif #endif