fmt с датой Говарда Хиннанта: почему "{}" от fmt :: to_string? Лучшая практика для FMT и даты? - PullRequest
1 голос
/ 17 июня 2020

TL; DR: я использую специальный форматировщик для fmt и библиотеки date Говарда Хиннанта. С date::year_month_day d{};, почему fmt::to_string(d) возвращает "{}", а fmt::format("{}", d) работает нормально, возвращая "0000-00-00"? Пример на godbolt .


Я использую библиотеку date и пытаюсь переключиться с 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: насколько мне известно, нет полной реализации частей календаря и часового пояса C ++ 20 std :: chrono по состоянию на июнь 2020 года.

Обновление: использование настраиваемого средства форматирования для настраиваемой пустой структуры отлично работает, давая тот же результат для format("{}", s) и to_string(s), см. Примеры по ссылке Godbolt выше. Так что в date::year_month_day должно быть что-то особенное, что ломает fmt::to_string().

1 Ответ

2 голосов
/ 17 июня 2020

Это неудачный эффект поиска, зависящего от аргументов: fmt::to_string вызывает format, который в конечном итоге разрешается в date::format вместо fmt::format. Исправление состоит в том, чтобы полностью квалифицировать вызов format в fmt::to_string, поскольку он зависит от определенного пользователем типа.

Обновление: это было исправлено в https://github.com/fmtlib/fmt/commit/2cac8a9d2e36cd920a9a60ec5b776c187e843fbb.

...