#pragma once #include #include // Formattable types can specialize this to true and will get automatic fmt formattering support via // their .ToString() method. namespace llarp { // Types can opt-in to being formatting via .ToString() by specializing this to true. This also // allows scoped enums by instead looking for a call to `ToString(val)` (and so there should be a // ToString function in the same namespace as the scoped enum to pick it up via ADL). template constexpr bool IsToStringFormattable = false; // e.g.: // template <> inline constexpr bool IsToStringFormattable = true; #ifdef __cpp_lib_is_scoped_enum using std::is_scoped_enum; using std::is_scoped_enum_v; #else template > struct is_scoped_enum : std::false_type {}; template struct is_scoped_enum : std::bool_constant>> {}; template constexpr bool is_scoped_enum_v = is_scoped_enum::value; #endif } // namespace llarp #if !defined(USE_GHC_FILESYSTEM) && FMT_VERSION >= 80102 // Native support in fmt added after fmt 8.1.1 #include #else #include namespace fmt { template <> struct formatter : formatter { template auto format(const fs::path& p, FormatContext& ctx) const { return formatter::format(p.string(), ctx); } }; } // namespace fmt #endif namespace fmt { template struct formatter>> : formatter { template auto format(const T& val, FormatContext& ctx) const { if constexpr (llarp::is_scoped_enum_v) return formatter::format(ToString(val), ctx); else return formatter::format(val.ToString(), ctx); } }; } // namespace fmt