English 中文(简体)
fmt在升级至10及以上时没有编辑。
原标题:fmt failed to compile while formatting enum after upgrading to v10 and above

鉴于成功编纂的代码为fmt v9.1,但因fmt v10+

It tripped me a while before I found github issues with correct keywords enum and compilation. Also github issues are not stating version in title..
This is a defined behavior for fmt v10+

#include <iostream>
#include <fmt/core.h>
#include <fmt/ostream.h>
using Test = enum Test_e{
    A,B,C
};

int main(int, char **)
{
    fmt::print(std::cout, "test enum {}
", A);
}

When libfmt is upgraded to v10.0, following error messages pop up.:
Live Demo
Another live demo with better layout Thanks to @Marek R

深层的相关问题

Error msg for C++11

In file included from <source>:2:
/opt/compiler-explorer/libs/fmt/10.0.0/include/fmt/core.h: In instantiation of  fmt::v10::detail::value<Context> fmt::v10::detail::make_value(T&&) [with Context = fmt::v10::basic_format_context<fmt::v10::appender, char>; T = Test_e&] :
/opt/compiler-explorer/libs/fmt/10.0.0/include/fmt/core.h:1711:29:   required from  fmt::v10::detail::value<Context> fmt::v10::detail::make_arg(T&&) [with bool IS_PACKED = true; Context = fmt::v10::basic_format_context<fmt::v10::appender, char>; type <anonymous> = fmt::v10::detail::type::custom_type; T = Test_e&; typename std::enable_if<IS_PACKED, int>::type <anonymous> = 0] 
/opt/compiler-explorer/libs/fmt/10.0.0/include/fmt/core.h:1827:77:   required from  fmt::v10::format_arg_store<Context, Args>::format_arg_store(T&& ...) [with T = {Test_e&}; Context = fmt::v10::basic_format_context<fmt::v10::appender, char>; Args = {Test_e}] 
/opt/compiler-explorer/libs/fmt/10.0.0/include/fmt/core.h:1844:31:   required from  constexpr fmt::v10::format_arg_store<Context, typename std::remove_cv<typename std::remove_reference<T>::type>::type ...> fmt::v10::make_format_args(T&& ...) [with Context = basic_format_context<appender, char>; T = {Test_e&}] 
/opt/compiler-explorer/libs/fmt/10.0.0/include/fmt/ostream.h:179:44:   required from  void fmt::v10::print(std::ostream&, format_string<T ...>, T&& ...) [with T = {Test_e}; std::ostream = std::basic_ostream<char>; format_string<T ...> = basic_format_string<char, Test_e>] 
<source>:10:15:   required from here
/opt/compiler-explorer/libs/fmt/10.0.0/include/fmt/core.h:1691:7: error: static assertion failed: Cannot format an argument. To make type T formattable provide a formatter<T> specialization: https://fmt.dev/latest/api.html#udt
 1691 |       formattable,
      |       ^~~~~~~~~~~
/opt/compiler-explorer/libs/fmt/10.0.0/include/fmt/core.h:1691:7: note:  formattable  evaluates to false
Compiler returned: 1
问题回答

这是遵守<代码>std:format的界定行为。 在fmt v10+之后,enum enum 必须具有各自的专业性。

Solutions:

  1. Overload format_as() for specific enum
  2. Cast the argument by fmt::underlying()
  3. Overload format_as() for every enum (it is requires in every namespace of the enum)
  4. Specialize your own fmt::formatter<T> (it works globally) (Referenced answer)

Overload format_as() for specific enum

通过format_as (refer to

#include <fmt/format.h>

namespace kevin_namespacy {
enum class film {
  house_of_cards, american_beauty, se7en = 7
};
auto format_as(film f) { return fmt::underlying(f); }
}

int main() {
  fmt::print("{}
", kevin_namespacy::film::se7en); // prints "7"
}

Cast the argument by fmt::underlying()

例如:fmt:print("{},fmt:underlying(e));

Overload format_as() for enum universally

C++20 Live Demo Note: the overloaded format_as() must be in the same namespace of enum. In the example, enum Test doesn t have namespace.

#include <iostream>
#include <type_traits>
#include <fmt/core.h>
#include <fmt/ostream.h>
using Test = enum Test_e{
    A,B,C
};

template<typename T>
requires std::is_enum_v<T>
auto format_as(T t) { return fmt::underlying(t); } 

int main(int, char **)
{
    fmt::print(std::cout, "test enum {}
", A);
}

C++11 Live

#include <iostream>
#include <type_traits>
#include <fmt/core.h>
#include <fmt/ostream.h>
using Test = enum Test_e{
    A,B,C
};

template<typename T, typename = std::enable_if<std::is_enum<T>::value, bool>>
auto format_as(T t) -> typename std::underlying_type<T>::type { 
    fmt::print("enum format_as
");
    return fmt::underlying(t); 
} 

int main(int, char **)
{
    fmt::print(std::cout, "test enum {}
", A);
    fmt::print(std::cout, "test number{}
", 10);
}

Specialize your own fmt::formatter<T>

Live Demo DasMoeh s contribution to this response

template <typename EnumType>
requires std::is_enum_v<EnumType>
struct fmt::formatter<EnumType> : fmt::formatter<std::underlying_type_t<EnumType>>
{
    // Forwards the formatting by casting the enum to it s underlying type
    auto format(const EnumType& enumValue, format_context& ctx) const
    {
        return fmt::formatter<std::underlying_type_t<EnumType>>::format(
            static_cast<std::underlying_type_t<EnumType>>(enumValue), ctx);
    }
};




相关问题
Undefined reference

I m getting this linker error. I know a way around it, but it s bugging me because another part of the project s linking fine and it s designed almost identically. First, I have namespace LCD. Then I ...

C++ Equivalent of Tidy

Is there an equivalent to tidy for HTML code for C++? I have searched on the internet, but I find nothing but C++ wrappers for tidy, etc... I think the keyword tidy is what has me hung up. I am ...

Template Classes in C++ ... a required skill set?

I m new to C++ and am wondering how much time I should invest in learning how to implement template classes. Are they widely used in industry, or is this something I should move through quickly?

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

typedef ing STL wstring

Why is it when i do the following i get errors when relating to with wchar_t? namespace Foo { typedef std::wstring String; } Now i declare all my strings as Foo::String through out the program, ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

Window iconification status via Xlib

Is it possible to check with the means of pure X11/Xlib only whether the given window is iconified/minimized, and, if it is, how?

热门标签