mirror of
https://github.com/CHN-beta/nixos.git
synced 2026-01-11 16:49:22 +08:00
72 lines
3.0 KiB
C++
72 lines
3.0 KiB
C++
# pragma once
|
|
# include <variant>
|
|
# include <experimental/memory>
|
|
# include <fmt/ostream.h>
|
|
# include <biu/string.hpp>
|
|
# include <biu/concepts.hpp>
|
|
|
|
namespace biu
|
|
{
|
|
namespace concepts
|
|
{ template <typename T, typename Char = char> concept Formattable = fmt::is_formattable<T, Char>::value; }
|
|
using concepts::Formattable;
|
|
|
|
namespace detail_
|
|
{
|
|
template <typename Char, Char... c> struct FormatLiteralHelper : protected BasicStaticString<Char, c...>
|
|
{template <typename... Param> std::basic_string<Char> operator()(Param&&... param) const;};
|
|
}
|
|
inline namespace literals
|
|
{ template <typename Char, Char... c> consteval detail_::FormatLiteralHelper<Char, c...> operator""_f(); }
|
|
|
|
namespace detail_
|
|
{
|
|
template <typename T> concept OptionalWrap
|
|
= SpecializationOf<T, std::optional> || SpecializationOf<T, std::shared_ptr>
|
|
|| SpecializationOf<T, std::weak_ptr> || SpecializationOf<T, std::unique_ptr>
|
|
|| SpecializationOf<T, std::experimental::observer_ptr>;
|
|
template <typename Wrap> struct UnderlyingTypeOfOptionalWrap;
|
|
template <typename Wrap> requires requires() {typename Wrap::value_type;}
|
|
struct UnderlyingTypeOfOptionalWrap<Wrap>
|
|
{using Type = std::remove_cvref_t<typename Wrap::value_type>;};
|
|
template <typename Wrap> requires requires() {typename Wrap::element_type;}
|
|
struct UnderlyingTypeOfOptionalWrap<Wrap>
|
|
{using Type = std::remove_cvref_t<typename Wrap::element_type>;};
|
|
template <typename T> struct FormatterReuseProxy
|
|
{
|
|
constexpr auto parse(fmt::format_parse_context& ctx)
|
|
-> std::invoke_result_t<decltype(&fmt::format_parse_context::begin), fmt::format_parse_context>;
|
|
};
|
|
template <typename T>
|
|
requires (!SpecializationOf<T, std::weak_ptr> && std::default_initializable<fmt::formatter<T>>)
|
|
struct FormatterReuseProxy<T> : fmt::formatter<T> {};
|
|
}
|
|
inline namespace stream_operators
|
|
{
|
|
template <typename Char, typename... Ts> requires (sizeof...(Ts) > 0) std::basic_ostream<Char>& operator<<
|
|
(std::basic_ostream<Char>& os, const std::variant<Ts...>& value);
|
|
}
|
|
}
|
|
|
|
namespace fmt
|
|
{
|
|
template <typename Char, biu::detail_::OptionalWrap Wrap> struct formatter<Wrap, Char>
|
|
: biu::detail_::FormatterReuseProxy<typename biu::detail_::UnderlyingTypeOfOptionalWrap<Wrap>::Type>
|
|
{
|
|
template <typename FormatContext> auto format(const Wrap& wrap, FormatContext& ctx)
|
|
-> std::invoke_result_t<decltype(&FormatContext::out), FormatContext>;
|
|
};
|
|
|
|
template <typename Char, biu::Enumerable T> struct formatter<T, Char>
|
|
{
|
|
bool full = false;
|
|
constexpr auto parse(fmt::format_parse_context& ctx)
|
|
-> std::invoke_result_t<decltype(&fmt::format_parse_context::begin), fmt::format_parse_context>;
|
|
template <typename FormatContext> auto format(const T& value, FormatContext& ctx)
|
|
-> std::invoke_result_t<decltype(&FormatContext::out), FormatContext>;
|
|
};
|
|
|
|
template <typename Char, typename... Ts> struct formatter<std::variant<Ts...>, Char>
|
|
: basic_ostream_formatter<Char> {};
|
|
}
|