50 lines
1.3 KiB
C++
50 lines
1.3 KiB
C++
#pragma once
|
|
|
|
#include "move.hpp"
|
|
#include "type_traits.hpp"
|
|
#include <format>
|
|
#include <string_view>
|
|
|
|
namespace util {
|
|
|
|
template <typename... Ts>
|
|
inline constexpr auto format(std::string_view fmt, Ts&&... args)
|
|
-> std::string {
|
|
return std::vformat(fmt, std::make_format_args(std::forward<Ts>(args)...));
|
|
}
|
|
|
|
template <typename T, typename Context>
|
|
using has_formatter =
|
|
std::is_constructible<typename Context::template formatter_type<T>>;
|
|
|
|
template <typename T>
|
|
using is_formattable = has_formatter<T, std::format_context>;
|
|
|
|
template <typename T>
|
|
inline constexpr bool is_formattable_v = is_formattable<T>::value;
|
|
|
|
template <typename T>
|
|
concept formattable = is_formattable_v<T>;
|
|
} // namespace util
|
|
|
|
#include <optional>
|
|
|
|
template<util::formattable F>
|
|
struct std::formatter<std::optional<F>> : public std::formatter<F> {
|
|
template <typename FormatContext>
|
|
auto format(const std::optional<F>& option, FormatContext& ctx)
|
|
-> decltype(ctx.out()) {
|
|
auto fmt = ctx.out();
|
|
|
|
if (option.has_value()) {
|
|
fmt = std::format_to(fmt, "Some(");
|
|
ctx.advance_to(fmt);
|
|
fmt = std::formatter<F>::format(option.value(), ctx);
|
|
*fmt++ = ')';
|
|
} else {
|
|
fmt = std::format_to(fmt, "None");
|
|
}
|
|
|
|
return fmt;
|
|
}
|
|
}; |