From d1e68f25dd9ce56c623cfdd96425bad0fa35dcdb Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Sat, 18 Sep 2021 01:09:23 +1000 Subject: util/strformat.h, util/delegate.h: More cleanup and future-proofing. * util/strformat.h: Found a SFINAE trick to detect absence of stream-out operators. Fixes building with C++20 standard library (#6275). * util/delegate.h: Fixed a commend and removed an unused declaration from MSVC member function pointer wrapper. * util/delegate.h: Added support for discarding functoid return values for delegates returning void. * util/delegate.h: Added support for using std::ref to bind non-copyable functoids. --- src/lib/util/strformat.h | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) (limited to 'src/lib/util/strformat.h') diff --git a/src/lib/util/strformat.h b/src/lib/util/strformat.h index a3ba1d11261..4714b9f5e71 100644 --- a/src/lib/util/strformat.h +++ b/src/lib/util/strformat.h @@ -132,6 +132,7 @@ - Inappropriate type for parameterised width/precision - Positional width/precision specifier not terminated with $ - Inappropriate type for n conversion + - Default conversion for type that lacks stream out operator Some limitations have been described in passing. Major limitations and bugs include: @@ -589,42 +590,30 @@ private: template using unsigned_integer_semantics = std::bool_constant && !std::is_signed_v >; - static void apply_signed(Stream &str, char16_t const &value) - { - str << std::make_signed_t(std::uint_least16_t(value)); - } - static void apply_signed(Stream &str, char32_t const &value) - { - str << std::make_signed_t(std::uint_least32_t(value)); - } template static std::enable_if_t, std::make_signed_t > || std::is_integral_v > apply_signed(Stream &str, U const &value) { if constexpr (std::is_same_v, std::make_signed_t >) str << int(std::make_signed_t(value)); - else if constexpr (std::is_signed_v) + else if constexpr (!std::is_signed_v || std::is_same_v) + str << std::make_signed_t(value); + else if constexpr (std::is_invocable_v decltype(x << y) { return x << y; }), Stream &, U const &>) str << value; else str << std::make_signed_t(value); } - static void apply_unsigned(Stream &str, char16_t const &value) - { - str << std::uint_least16_t(value); - } - static void apply_unsigned(Stream &str, char32_t const &value) - { - str << std::uint_least32_t(value); - } template static std::enable_if_t, std::make_unsigned_t > || std::is_integral_v > apply_unsigned(Stream &str, U const &value) { if constexpr (std::is_same_v, std::make_unsigned_t >) str << unsigned(std::make_unsigned_t(value)); - else if constexpr (std::is_signed_v) + else if constexpr (!std::is_unsigned_v || std::is_same_v) str << std::make_unsigned_t(value); - else + else if constexpr (std::is_invocable_v decltype(x << y) { return x << y; }), Stream &, U const &>) str << value; + else + str << std::make_unsigned_t(value); } public: @@ -830,7 +819,15 @@ public: str << reinterpret_cast(std::uintptr_t(value)); break; default: - str << value; + if constexpr (std::is_invocable_v decltype(x << y) { return x << y; }), Stream &, U const &>) + { + str << value; + } + else + { + assert(false); // stream out operator not declared or declared deleted + str << '?'; + } } } else -- cgit v1.2.3-70-g09d2