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.

Другие вопросы по тегам