Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compiler fails to find custom formatter when target is wide string (fmt 8.1.1) #3099

Closed
artemyv opened this issue Sep 13, 2022 · 3 comments
Closed
Labels

Comments

@artemyv
Copy link

artemyv commented Sep 13, 2022

We have recently switched from fmt lib 8.0.1 to 8.1.1
Formatting class enums stopped working by default (as int)

I was trying to use answers from #391 (comment) to create a custom formatter.
It works when target is string and does not find the proper function when target is wstring.

What is wrong with my code?

#include <string_view>
#include <fmt/xchar.h>

namespace CoreCommon {
    enum class RDSRole {
        AutoDetect,
        Enabled,
        Disabled
    };
}

template <typename Char>
struct fmt::formatter<CoreCommon::RDSRole, Char> : formatter<std::basic_string_view<Char>>
{
    template <typename FormatContext>
    auto format(CoreCommon::RDSRole role, FormatContext &ctx)
    {
        std::basic_string_view<Char> name;
        switch (role)
        {
        case CoreCommon::RDSRole::AutoDetect:
            if constexpr (std::is_same<Char, char>::value)
                name = "auto";
            else
                name = L"auto";
            break;
        case CoreCommon::RDSRole::Enabled:
            if constexpr (std::is_same<Char, char>::value)
                name = "enabled";
            else
                name = L"enabled";
            break;
        case CoreCommon::RDSRole::Disabled:
            if constexpr (std::is_same<Char, char>::value)
                name = "disabled";
            else
                name = L"disabled";
            break;
        default:
            if constexpr (std::is_same<Char, char>::value)
                name = "unknown";
            else
                name = L"unknown";
            break;
        }
        return formatter<std::basic_string_view<Char>>::format(name, ctx);
    }
};
int main()
{
    fmt::print("Hello {}!\n", "World");
    fmt::print(L"Hello {}!\n", L"World");

    auto role = CoreCommon::RDSRole::AutoDetect;
    auto msg = fmt::format("RDS={}", role);

    fmt::print("Role {}!\n", msg);
    auto wmsg = fmt::format(L"RDS={}", role); //this line fails (or formats as int in older fmt lib

    fmt::print(L"Role {}!\n", wmsg);
    return 0;
}

Could you give me a hint how to resolve the issue?

@artemyv
Copy link
Author

artemyv commented Sep 13, 2022

BTW - I'm compiling as c++17 under MSVC 2017 and 2019

@vitaut
Copy link
Contributor

vitaut commented Sep 13, 2022

Your formatter specialization is defined incorrectly because it inherits from formatter<std::basic_string_view<Char>> instead of formatter<std::basic_string_view<Char>, Char>. Fixing this will make the enum formattable with wide format.

@artemyv
Copy link
Author

artemyv commented Sep 13, 2022

Thanks, that has solved my issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants