带有 {fmt} 库和 Visual Studio 2022 (17.2.2) 的用户定义类型

User-defined types with {fmt} library and Visual Studio 2022 (17.2.2)

我正在使用https://github.com/fmtlib/fmt (commit hash 7e4ad40171aa552d38cb99a5c181a0d7b150facc - at the time of this writing pretty new) with the newest Visual Studio 2022 version (17.2.2) and following this tutorial here

我想让这个工作:

struct complex
{
  double a;
  double b;
};

template<>
struct fmt::formatter<complex>
{
  template<typename ParseContext>
  constexpr auto parse(ParseContext& ctx) { return ctx.begin(); }

  template<typename FormatContext>
  auto format(complex const& number, FormatContext& ctx) {
    return format_to(ctx.out(), "{0} +i{1}", number.a, number.b);
  }
};
// ...

// somewhere in main
complex number{1, 2};
std::string message = fmt::format("The number is {}.\n", number);

我收到错误消息:

ERROR: G:/dev/piper/devertexwahn/flatland/tests/third_party/BUILD.bazel:42:8: Compiling flatland/tests/third_party/fmt_test.cpp failed: (Exit 2): cl.exe failed: error executing command C:\Program Files\Microsoft Visual Studio22\Community\VC\Tools\MSVC.32.31326\bin\HostX64\x64\cl.exe /nologo /DCOMPILER_MSVC /DNOMINMAX /D_WIN32_WINNT=0x0601 /D_CRT_SECURE_NO_DEPRECATE ... (remaining 44 arguments skipped)
flatland/tests/third_party/fmt_test.cpp(53): error C2668: 'std::format_to': ambiguous call to overloaded function
C:\Program Files\Microsoft Visual Studio22\Community\VC\Tools\MSVC.32.31326\include\format(3046): note: could be '_OutputIt std::format_to<OutputIt,const double&,const double&>(_OutputIt,const std::_Basic_format_string<char,const double &,const double &>,const double &,const double &)' [found using argument-dependent lookup]
        with
        [
            _OutputIt=fmt::v8::appender,
            OutputIt=fmt::v8::appender
        ]
G:\bazel_output_base\execroot\de_vertexwahn\bazel-out\x64_windows-fastbuild\bin\external\fmt\_virtual_includes\fmt\fmt/core.h(3195): note: or       'OutputIt fmt::v8::format_to<OutputIt,const double&,const double&,0>(OutputIt,fmt::v8::basic_format_string<char,const double &,const double &>,const double &,const double &)'
        with
        [
            OutputIt=fmt::v8::appender
        ]
flatland/tests/third_party/fmt_test.cpp(52): note: while trying to match the argument list '(OutputIt, const char [10], const double, const double)'
        with
        [
            OutputIt=fmt::v8::appender
        ]
G:\bazel_output_base\execroot\de_vertexwahn\bazel-out\x64_windows-fastbuild\bin\external\fmt\_virtual_includes\fmt\fmt/core.h(713): note: see reference to function template instantiation 'auto fmt::v8::formatter<complex,char,void>::format<Context>(const complex &,FormatContext &)' being compiled
        with
        [
            Context=fmt::v8::format_context,
            FormatContext=fmt::v8::format_context
        ]
G:\bazel_output_base\execroot\de_vertexwahn\bazel-out\x64_windows-fastbuild\bin\external\fmt\_virtual_includes\fmt\fmt/core.h(1457): note: see reference to function template instantiation 'bool fmt::v8::detail::has_const_formatter<U,Context>(void)' being compiled     
        with
        [
            U=complex,
            Context=fmt::v8::format_context
        ]
G:\bazel_output_base\execroot\de_vertexwahn\bazel-out\x64_windows-fastbuild\bin\external\fmt\_virtual_includes\fmt\fmt/core.h(1486): note: see reference to class template instantiation 'fmt::v8::detail::arg_mapper<Context>::formattable<const complex &,complex>' being compiled
        with
        [
            Context=fmt::v8::format_context
        ]
G:\bazel_output_base\execroot\de_vertexwahn\bazel-out\x64_windows-fastbuild\bin\external\fmt\_virtual_includes\fmt\fmt/core.h(1697): note: see reference to alias template instantiation 'fmt::v8::detail::mapped_type_constant<complex,Context>' being compiled
        with
        [
            Context=fmt::v8::format_context
        ]
G:\bazel_output_base\execroot\de_vertexwahn\bazel-out\x64_windows-fastbuild\bin\external\fmt\_virtual_includes\fmt\fmt/core.h(1858): note: see reference to function template instantiation 'unsigned __int64 fmt::v8::detail::encode_types<Context,complex,>(void)' being compiled
        with
        [
            Context=fmt::v8::format_context
        ]
G:\bazel_output_base\execroot\de_vertexwahn\bazel-out\x64_windows-fastbuild\bin\external\fmt\_virtual_includes\fmt\fmt/core.h(3167): note: see reference to class template instantiation 'fmt::v8::format_arg_store<fmt::v8::format_context,complex>' being compiled        
flatland/tests/third_party/fmt_test.cpp(59): note: see reference to function template instantiation 'std::string fmt::v8::format<complex&>(fmt::v8::basic_format_string<char,complex &>,complex &)' being compiled
G:\bazel_output_base\execroot\de_vertexwahn\bazel-out\x64_windows-fastbuild\bin\external\fmt\_virtual_includes\fmt\fmt/core.h(1696): error C2062: type 'unknown-type' unexpected
G:\bazel_output_base\execroot\de_vertexwahn\bazel-out\x64_windows-fastbuild\bin\external\fmt\_virtual_includes\fmt\fmt/core.h(1696): error C2144: syntax error: 'unknown-type' should be preceded by '('
G:\bazel_output_base\execroot\de_vertexwahn\bazel-out\x64_windows-fastbuild\bin\external\fmt\_virtual_includes\fmt\fmt/core.h(1697): error C2039: 'value': is not a member of '`global namespace''
G:\bazel_output_base\execroot\de_vertexwahn\bazel-out\x64_windows-fastbuild\bin\external\fmt\_virtual_includes\fmt\fmt/core.h(1855): error C3615: constexpr function 'fmt::v8::detail::encode_types' cannot result in a constant expression
G:\bazel_output_base\execroot\de_vertexwahn\bazel-out\x64_windows-fastbuild\bin\external\fmt\_virtual_includes\fmt\fmt/core.h(1858): note: failure was caused by control reaching the end of a constexpr function
Target //flatland/tests/third_party:fmt_test failed to build                                                                          
Use --verbose_failures to see the command lines of failed build steps. 

该代码似乎适用于 Ubuntu 20.04 上的 GCC9 以及 macOS 上的 Apple CLang。知道我在这里做错了什么吗?

错误是由C++20引入的std::format_to函数引起的。要修复它,请限定您对 fmt::format_to 的调用。例如,而不是

return format_to(ctx.out(), "{0} +i{1}", number.a, number.b);

改为这样做:

return fmt::format_to(ctx.out(), "{0} +i{1}", number.a, number.b);

有关详细信息,请参阅此问题:format conflict with Visual Studio 2022 17.2.0