From 2217d6b560d9030d66259f5b0feb292d5e515cff Mon Sep 17 00:00:00 2001 From: asynts Date: Wed, 7 Oct 2020 14:01:59 +0200 Subject: [PATCH] AK+Format: Add SFINAE wrapper 'FormatIfSupported'. --- AK/Format.h | 44 ++++++++++++++++++++++++++++++++++++++++- AK/Tests/TestFormat.cpp | 18 +++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/AK/Format.h b/AK/Format.h index cb8d31c39e..d66e9b607c 100644 --- a/AK/Format.h +++ b/AK/Format.h @@ -41,7 +41,9 @@ class FormatParser; class FormatBuilder; template -struct Formatter; +struct Formatter { + using __no_formatter_defined = void; +}; constexpr size_t max_format_arguments = 256; @@ -346,6 +348,44 @@ template void dbgln(const char* fmtstr, const Parameters&... parameters) { dbgln(StringView { fmtstr }, parameters...); } inline void dbgln() { raw_dbg("\n"); } +template +struct HasFormatter : TrueType { +}; +template +struct HasFormatter::__no_formatter_defined> : FalseType { +}; + +template +class FormatIfSupported { +public: + explicit FormatIfSupported(const T& value) + : m_value(value) + { + } + + const T& value() const { return m_value; } + +private: + const T& m_value; +}; +template +struct __FormatIfSupported : Formatter { + void format(TypeErasedFormatParams& params, FormatBuilder& builder, const FormatIfSupported&) + { + Formatter::format(params, builder, "?"); + } +}; +template +struct __FormatIfSupported : Formatter { + void format(TypeErasedFormatParams& params, FormatBuilder& builder, const FormatIfSupported& value) + { + Formatter::format(params, builder, value.value()); + } +}; +template +struct Formatter> : __FormatIfSupported::value> { +}; + } // namespace AK #ifndef KERNEL @@ -361,3 +401,5 @@ using AK::warnln; using AK::dbgln; using AK::new_dbg; using AK::raw_dbg; + +using AK::FormatIfSupported; diff --git a/AK/Tests/TestFormat.cpp b/AK/Tests/TestFormat.cpp index 0e7e9aae6a..7d426fb4e1 100644 --- a/AK/Tests/TestFormat.cpp +++ b/AK/Tests/TestFormat.cpp @@ -196,4 +196,22 @@ TEST_CASE(format_character) EXPECT_EQ(String::formatted("{}", true ? a : 'b'), "a"); } +struct A { +}; +struct B { +}; +template<> +struct AK::Formatter : Formatter { + void format(TypeErasedFormatParams& params, FormatBuilder& builder, B) + { + Formatter::format(params, builder, "B"); + } +}; + +TEST_CASE(format_if_supported) +{ + EXPECT_EQ(String::formatted("{}", FormatIfSupported { A {} }), "?"); + EXPECT_EQ(String::formatted("{}", FormatIfSupported { B {} }), "B"); +} + TEST_MAIN(Format)