diff --git a/Utilities/StrFmt.h b/Utilities/StrFmt.h index 131aa7152a..6e2878467c 100644 --- a/Utilities/StrFmt.h +++ b/Utilities/StrFmt.h @@ -15,7 +15,7 @@ namespace fmt template struct fmt_unveil { - static_assert(sizeof(T) > 0, "fmt_unveil<>: cannot pass forward-declared object"); + static_assert(sizeof(T) > 0, "fmt_unveil<> error: incomplete type"); using type = T; @@ -59,13 +59,24 @@ struct fmt_unveil::value && sizeof { using type = T; - // Convert FP to f64 and reinterpret (TODO?) - static inline u64 get(const f64 arg) + // Convert FP to f64 and reinterpret as u64 + static inline u64 get(const f64& arg) { return *reinterpret_cast(reinterpret_cast(&arg)); } }; +template <> +struct fmt_unveil +{ + using type = f16; + + static inline u64 get(const f16& arg) + { + return fmt_unveil::get(arg.operator float()); + } +}; + template struct fmt_unveil::value>> { @@ -126,15 +137,27 @@ struct fmt_class_string return *reinterpret_cast(static_cast(arg)); } + // Enum -> string function type + using convert_t = const char*(*)(T value); + + // Enum -> string function registered + static convert_t convert_enum; + // Helper function (safely converts arg to enum value) - static SAFE_BUFFERS FORCE_INLINE void format_enum(std::string& out, u64 arg, const char* (*get)(T value)) + static SAFE_BUFFERS FORCE_INLINE void format_enum(std::string& out, u64 arg, convert_t convert) { + // Save convert function + if (convert_enum == nullptr) + { + convert_enum = convert; + } + const auto value = static_cast>(arg); // Check narrowing if (static_cast(value) == arg) { - if (const char* str = get(static_cast(value))) + if (const char* str = convert(static_cast(value))) { out += str; return; @@ -180,6 +203,9 @@ struct fmt_class_string static constexpr const char* unknown = nullptr; }; +template +const char*(*fmt_class_string::convert_enum)(T) = nullptr; + template <> struct fmt_class_string {