diff options
author | 2021-09-18 01:09:23 +1000 | |
---|---|---|
committer | 2021-09-18 01:09:23 +1000 | |
commit | d1e68f25dd9ce56c623cfdd96425bad0fa35dcdb (patch) | |
tree | c8f7430c1ce45847001d493d8f7eee10a6b87ecf /src/lib/util/strformat.h | |
parent | 6e3adb71999938f3a05a5bae4f108c701af3e77a (diff) |
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.
Diffstat (limited to 'src/lib/util/strformat.h')
-rw-r--r-- | src/lib/util/strformat.h | 37 |
1 files changed, 17 insertions, 20 deletions
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 <typename U> using unsigned_integer_semantics = std::bool_constant<std::is_integral_v<U> && !std::is_signed_v<U> >; - static void apply_signed(Stream &str, char16_t const &value) - { - str << std::make_signed_t<std::uint_least16_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>(std::uint_least32_t(value)); - } template <typename U> static std::enable_if_t<std::is_same_v<std::make_signed_t<U>, std::make_signed_t<char> > || std::is_integral_v<U> > apply_signed(Stream &str, U const &value) { if constexpr (std::is_same_v<std::make_signed_t<U>, std::make_signed_t<char> >) str << int(std::make_signed_t<U>(value)); - else if constexpr (std::is_signed_v<U>) + else if constexpr (!std::is_signed_v<U> || std::is_same_v<typename Stream::char_type, U>) + str << std::make_signed_t<U>(value); + else if constexpr (std::is_invocable_v<decltype([] (auto &x, auto &y) -> decltype(x << y) { return x << y; }), Stream &, U const &>) str << value; else str << std::make_signed_t<U>(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 <typename U> static std::enable_if_t<std::is_same_v<std::make_unsigned_t<U>, std::make_unsigned_t<char> > || std::is_integral_v<U> > apply_unsigned(Stream &str, U const &value) { if constexpr (std::is_same_v<std::make_unsigned_t<U>, std::make_unsigned_t<char> >) str << unsigned(std::make_unsigned_t<U>(value)); - else if constexpr (std::is_signed_v<U>) + else if constexpr (!std::is_unsigned_v<U> || std::is_same_v<typename Stream::char_type, U>) str << std::make_unsigned_t<U>(value); - else + else if constexpr (std::is_invocable_v<decltype([] (auto &x, auto &y) -> decltype(x << y) { return x << y; }), Stream &, U const &>) str << value; + else + str << std::make_unsigned_t<U>(value); } public: @@ -830,7 +819,15 @@ public: str << reinterpret_cast<void const *>(std::uintptr_t(value)); break; default: - str << value; + if constexpr (std::is_invocable_v<decltype([] (auto &x, auto &y) -> decltype(x << y) { return x << y; }), Stream &, U const &>) + { + str << value; + } + else + { + assert(false); // stream out operator not declared or declared deleted + str << '?'; + } } } else |