summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/util/strformat.h
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2021-09-18 01:09:23 +1000
committer Vas Crabb <vas@vastheman.com>2021-09-18 01:09:23 +1000
commitd1e68f25dd9ce56c623cfdd96425bad0fa35dcdb (patch)
treec8f7430c1ce45847001d493d8f7eee10a6b87ecf /src/lib/util/strformat.h
parent6e3adb71999938f3a05a5bae4f108c701af3e77a (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.h37
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