如何使用 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
我想专门化一个格式化程序模板,这样我就可以写:
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