fmt с датой Говарда Хиннанта: почему "{}" от fmt::to_string? Лучшая практика для FMT и даты?
TL;DR: я использую специальный форматировщик для библиотеки дат fmt и Говарда Хиннанта. С участием date::year_month_day d{};
, Почему fmt::to_string(d)
возвращение "{}"
пока fmt::format("{}", d)
работает нормально, возвращается "0000-00-00"
? Пример на Godbolt.
Я использую библиотеку дат и пытаюсь переключиться с iostreams на fmt. Мне нужно отформатироватьdate::year_month_day
в формате ГГГГ-ММ-ДД, поэтому я написал настраиваемый модуль форматирования (специализация шаблона fmt::formatter для date::year_month_day
):
template<>
struct fmt::formatter<date::year_month_day> {
template<typename ParseContext>
auto parse(ParseContext & ctx) { return ctx.begin(); }
template<typename FormatContext>
auto format(const date::year_month_day & ymd, FormatContext & ctx) -> decltype(ctx.out()) {
const int year = (int)ymd.year();
const unsigned month = (unsigned)ymd.month();
const unsigned day = (unsigned)ymd.day();
return fmt::format_to(ctx.out(), "{:04}-{:02}-{:02}", year, month, day);
}
};
Полный минимальный рабочий пример, с двумя рабочими примерами и одним неудачным, доступен на Godbolt.
Используя это настраиваемое средство форматирования, fmt::format("{}", date::year_month_day{})
работает как положено, возвращается "0000-00-00"
. fmt::to_string(date::year_month_day{})
должен возвращать тот же результат, но возвращает "{}"
вместо.
Как лучше всего форматировать date::year_month_day
и другие виды из date
с участием fmt
, включая fmt::to_string()
? Почему я это понимаю"{}"
?
Я пока не могу использовать компилятор с поддержкой дат C++20: насколько мне известно, по состоянию на июнь 2020 года не существует полной реализации частей календаря и часового пояса std:: chrono C++20.
Обновление: использование настраиваемого средства форматирования для настраиваемой пустой структуры отлично работает, давая тот же результат для format("{}", s)
а также to_string(s)
см. примеры по ссылке выше на Godbolt. Так что в этом должно быть что-то особенноеdate::year_month_day
который ломается fmt::to_string()
.
1 ответ
Это неудачный эффект поиска, зависящего от аргумента: fmt::to_string
звонки format
который в конечном итоге решается на date::format
вместо того fmt::format
. Исправление состоит в том, чтобы полностью квалифицировать вызовformat
в fmt::to_string
поскольку это зависит от типа, определенного пользователем.
Обновление: это было исправлено в https://github.com/fmtlib/fmt/commit/2cac8a9d2e36cd920a9a60ec5b776c187e843fbb.