cpp-utils/include/format.hpp

58 lines
1.5 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 {
#if defined(__cpp_if_consteval) && defined(doesnt_work_yet_in_clang_14)
if
consteval { return std::format(fmt, args...); }
else {
return std::vformat(fmt, std::make_format_args(std::forward<Ts>(args)...));
}
#else
return std::vformat(fmt, std::make_format_args(std::forward<Ts>(args)...));
#endif
}
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;
}
};