mirror of
https://github.com/SerenityOS/serenity
synced 2024-09-06 17:06:31 +00:00
AK+Format: Add SFINAE wrapper 'FormatIfSupported'.
This commit is contained in:
parent
afef05ece2
commit
2217d6b560
44
AK/Format.h
44
AK/Format.h
|
@ -41,7 +41,9 @@ class FormatParser;
|
|||
class FormatBuilder;
|
||||
|
||||
template<typename T, typename = void>
|
||||
struct Formatter;
|
||||
struct Formatter {
|
||||
using __no_formatter_defined = void;
|
||||
};
|
||||
|
||||
constexpr size_t max_format_arguments = 256;
|
||||
|
||||
|
@ -346,6 +348,44 @@ template<typename... Parameters>
|
|||
void dbgln(const char* fmtstr, const Parameters&... parameters) { dbgln(StringView { fmtstr }, parameters...); }
|
||||
inline void dbgln() { raw_dbg("\n"); }
|
||||
|
||||
template<typename T, typename = void>
|
||||
struct HasFormatter : TrueType {
|
||||
};
|
||||
template<typename T>
|
||||
struct HasFormatter<T, typename Formatter<T>::__no_formatter_defined> : FalseType {
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class FormatIfSupported {
|
||||
public:
|
||||
explicit FormatIfSupported(const T& value)
|
||||
: m_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
const T& value() const { return m_value; }
|
||||
|
||||
private:
|
||||
const T& m_value;
|
||||
};
|
||||
template<typename T, bool Supported = false>
|
||||
struct __FormatIfSupported : Formatter<StringView> {
|
||||
void format(TypeErasedFormatParams& params, FormatBuilder& builder, const FormatIfSupported<T>&)
|
||||
{
|
||||
Formatter<StringView>::format(params, builder, "?");
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
struct __FormatIfSupported<T, true> : Formatter<T> {
|
||||
void format(TypeErasedFormatParams& params, FormatBuilder& builder, const FormatIfSupported<T>& value)
|
||||
{
|
||||
Formatter<T>::format(params, builder, value.value());
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
struct Formatter<FormatIfSupported<T>> : __FormatIfSupported<T, HasFormatter<T>::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;
|
||||
|
|
|
@ -196,4 +196,22 @@ TEST_CASE(format_character)
|
|||
EXPECT_EQ(String::formatted("{}", true ? a : 'b'), "a");
|
||||
}
|
||||
|
||||
struct A {
|
||||
};
|
||||
struct B {
|
||||
};
|
||||
template<>
|
||||
struct AK::Formatter<B> : Formatter<StringView> {
|
||||
void format(TypeErasedFormatParams& params, FormatBuilder& builder, B)
|
||||
{
|
||||
Formatter<StringView>::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)
|
||||
|
|
Loading…
Reference in a new issue