如何使用 wchar_t 为 fmt 编写格式化程序?

How to write a formatter for fmt using wchar_t?

我想专门化一个格式化程序模板,这样我就可以写:

rect    rc(0, 0, 100, 20);
wstring buf = fmt_msg(L"{0}", rc);

我有这个:

ea::wstring
vfmt_msg(const ea::wstring &msg, fmt::wformat_args args) {
  std::wstring s_ = fmt::vformat(std::wstring(msg.data()), args);
  return ea::wstring(s_.data());
}

template <typename... TArgs>
wstring
fmt_msg(wstring cc &format, TArgs cc &... args) {
  return vfmt_msg(format, fmt::make_format_args<fmt::wformat_context>(args...));
}

namespace fmt {
template <> struct formatter<rect> {
  template <typename ParseContext> constexpr auto parse(ParseContext &ctx) {
    return ctx.begin();
  }
  template <typename FormatContext>
  auto format(const rect &rc, FormatContext &ctx) {
    return format_to(ctx.begin(), L"{{({}, {}, {}, {}), cx: {}, cy: {}}}", rc.x,
                     rc.y, rc.x2, rc.y2, rc.cx(), rc.cy());
  }
};
} // namespace fmt

但我明白了:

fmt\core.h(844,1): error C2664:  'const void *fmt::v5::internal::arg_mapper<Context>::map(std::nullptr_t)': cannot convert argument 1 from 'Arg' to 'signed char'
fmt\core.h(844,1): error C2664:         with
fmt\core.h(844,1): error C2664:         [
fmt\core.h(844,1): error C2664:             Context=fmt::v5::basic_format_context<std::back_insert_iterator<fmt::v5::internal::buffer<wchar_t>>,wchar_t>
fmt\core.h(844,1): error C2664:         ]
fmt\core.h(844,1): error C2664:         and
fmt\core.h(844,1): error C2664:         [
fmt\core.h(844,1): error C2664:             Arg=rect
fmt\core.h(844,1): error C2664:         ] (compiling source file trace.cpp)
fmt\core.h(844,69): message :  No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called (compiling source file trace.cpp)
fmt\core.h(1000): message :  see reference to alias template instantiation 'fmt::v5::internal::mapped_type_constant<rect,fmt::v5::basic_format_context<std::back_insert_iterator<fmt::v5::internal::buffer<wchar_t>>,wchar_t>>' being compiled (compiling source file trace.cpp)
fmt\core.h(1102): message :  see reference to function template instantiation 'unsigned __int64 fmt::v5::internal::encode_types<Context,rect,>(void)' being compiled
fmt\core.h(1102): message :         with
fmt\core.h(1102): message :         [
fmt\core.h(1102): message :             Context=fmt::v5::basic_format_context<std::back_insert_iterator<fmt::v5::internal::buffer<wchar_t>>,wchar_t>
fmt\core.h(1102): message :         ] (compiling source file trace.cpp)
core\typedefs.h(124): message :  see reference to class template instantiation 'fmt::v5::format_arg_store<fmt::v5::basic_format_context<std::back_insert_iterator<fmt::v5::internal::buffer<wchar_t>>,wchar_t>,rect>' being compiled (compiling source file trace.cpp)
core\trace.cpp(73): message :  see reference to function template instantiation 'wstring fmt_msg<rect>(const wstring &,const rect &)' being compiled

但如果我在 char 上执行此操作,它会起作用,所以我尝试了:

namespace fmt {
template <> struct formatter<rect, wchar_t> {
  template <typename ParseContext> constexpr auto parse(ParseContext &ctx) {
    return ctx.begin();
  }
  template <typename FormatContext>
  auto format(const rect &rc, FormatContext &ctx) {
    return format_to(ctx.begin(), "{{({}, {}, {}, {}), cx: {}, cy: {}}}", rc.x,
                     rc.y, rc.x2, rc.y2, rc.cx(), rc.cy());
  }
};
} // namespace fmt

注意模板 <> struct formatter < rect, wchar_t > part

但我得到:

core\trace.cpp(55,1): error C2039:  'begin': is not a member of 'fmt::v5::basic_format_context<std::back_insert_iterator<fmt::v5::internal::buffer<wchar_t>>,wchar_t>'
fmt\core.h(1074): message :  see declaration of 'fmt::v5::basic_format_context<std::back_insert_iterator<fmt::v5::internal::buffer<wchar_t>>,wchar_t>'
fmt\core.h(740): message :  see reference to function template instantiation 'auto fmt::v5::formatter<rect,wchar_t,void>::format<Context>(const rect &,FormatContext &)' being compiled
fmt\core.h(740): message :         with
fmt\core.h(740): message :         [
fmt\core.h(740): message :             Context=fmt::v5::wformat_context,
fmt\core.h(740): message :             FormatContext=fmt::v5::wformat_context
fmt\core.h(740): message :         ] (compiling source file trace.cpp)
fmt\core.h(727): message :  see reference to function template instantiation 'void fmt::v5::internal::value<Context>::format_custom_arg<T,fmt::v5::formatter<rect,wchar_t,void>>(const void *,fmt::v5::basic_parse_context<wchar_t,fmt::v5::internal::error_handler> &,Context &)' being compiled
fmt\core.h(727): message :         with
fmt\core.h(727): message :         [
fmt\core.h(727): message :             Context=fmt::v5::wformat_context,
fmt\core.h(727): message :             T=rect
fmt\core.h(727): message :         ] (compiling source file trace.cpp)
fmt\core.h(724): message :  see reference to function template instantiation 'void fmt::v5::internal::value<Context>::format_custom_arg<T,fmt::v5::formatter<rect,wchar_t,void>>(const void *,fmt::v5::basic_parse_context<wchar_t,fmt::v5::internal::error_handler> &,Context &)' being compiled
fmt\core.h(724): message :         with
fmt\core.h(724): message :         [
fmt\core.h(724): message :             Context=fmt::v5::wformat_context,
fmt\core.h(724): message :             T=rect
fmt\core.h(724): message :         ] (compiling source file trace.cpp)
fmt\core.h(1015): message :  see reference to function template instantiation 'fmt::v5::internal::value<Context>::value<T>(const T &)' being compiled
fmt\core.h(1015): message :         with
fmt\core.h(1015): message :         [
fmt\core.h(1015): message :             Context=fmt::v5::wformat_context,
fmt\core.h(1015): message :             T=rect
fmt\core.h(1015): message :         ] (compiling source file trace.cpp)
fmt\core.h(1015): message :  see reference to function template instantiation 'fmt::v5::internal::value<Context>::value<T>(const T &)' being compiled
fmt\core.h(1015): message :         with
fmt\core.h(1015): message :         [
fmt\core.h(1015): message :             Context=fmt::v5::wformat_context,
fmt\core.h(1015): message :             T=rect
fmt\core.h(1015): message :         ] (compiling source file trace.cpp)
fmt\core.h(1105): message :  see reference to function template instantiation 'fmt::v5::internal::value<Context> fmt::v5::internal::make_arg<true,Context,rect,0>(const T &)' being compiled
fmt\core.h(1105): message :         with
fmt\core.h(1105): message :         [
fmt\core.h(1105): message :             Context=fmt::v5::wformat_context,
fmt\core.h(1105): message :             T=rect
fmt\core.h(1105): message :         ] (compiling source file trace.cpp)
fmt\core.h(1105): message :  while compiling class template member function 'fmt::v5::format_arg_store<fmt::v5::basic_format_context<std::back_insert_iterator<fmt::v5::internal::buffer<wchar_t>>,wchar_t>,rect>::format_arg_store(const rect &)' (compiling source file trace.cpp)
fmt\core.h(1120): message :  see reference to function template instantiation 'fmt::v5::format_arg_store<fmt::v5::basic_format_context<std::back_insert_iterator<fmt::v5::internal::buffer<wchar_t>>,wchar_t>,rect>::format_arg_store(const rect &)' being compiled (compiling source file trace.cpp)
core\typedefs.h(125): message :  see reference to class template instantiation 'fmt::v5::format_arg_store<fmt::v5::basic_format_context<std::back_insert_iterator<fmt::v5::internal::buffer<wchar_t>>,wchar_t>,rect>' being compiled (compiling source file trace.cpp)
core\trace.cpp(73): message :  see reference to function template instantiation 'wstring fmt_msg<rect>(const wstring &,const rect &)' being compiled

要修复编译器错误,请在 auto format(const rect &rc, FormatContext &ctx) {

替换

return format_to(ctx.begin(), ...

return format_to(ctx.out(), ...

根据用户定义的类型示例@https://github.com/fmtlib/fmt