After updating Visual Studio Professional 2022 to version 17.2.0 (compiler version 19.32.31328 for x64), Formatting User-defined Types example no longer compiles.
This might be a bug in Visual Studio, but would still be good to have a work around.
I could not repro with compiler explorer, it might not have this compiler version of yet.
#include <mutex> // comment to remove the issue
#include <fmt/format.h>
struct point {
double x, y;
};
template <> struct fmt::formatter<point> {
// Presentation format: 'f' - fixed, 'e' - exponential.
char presentation = 'f';
// Parses format specifications of the form ['f' | 'e'].
constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
// [ctx.begin(), ctx.end()) is a character range that contains a part of
// the format string starting from the format specifications to be parsed,
// e.g. in
//
// fmt::format("{:f} - point of interest", point{1, 2});
//
// the range will contain "f} - point of interest". The formatter should
// parse specifiers until '}' or the end of the range. In this example
// the formatter should parse the 'f' specifier and return an iterator
// pointing to '}'.
// Parse the presentation format and store it in the formatter:
auto it = ctx.begin(), end = ctx.end();
if (it != end && (*it == 'f' || *it == 'e')) presentation = *it++;
// Check if reached the end of the range:
if (it != end && *it != '}') throw format_error("invalid format");
// Return an iterator past the end of the parsed range:
return it;
}
// Formats the point p using the parsed format specification (presentation)
// stored in this formatter.
template <typename FormatContext>
auto format(const point& p, FormatContext& ctx) -> decltype(ctx.out()) {
// ctx.out() is an output iterator to write to.
return presentation == 'f'
? format_to(ctx.out(), "({:.1f}, {:.1f})", p.x, p.y)
: format_to(ctx.out(), "({:.1e}, {:.1e})", p.x, p.y);
}
};
int main(int, char**)
{
point p = {1, 2};
fmt::print("{}", p);
return 0;
}
Build started...
1>------ Build started: Project: foo, Configuration: Debug x64 ------
1>foo.cpp
1>foo.cpp(42): error C2668: 'fmt::v8::format_to': ambiguous call to overloaded function
1>fmt-src\include\fmt\core.h(3203): note: could be '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 &)'
1> with
1> [
1> OutputIt=fmt::v8::appender
1> ]
1>C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.32.31326\include\format(3046): note: or '_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]
1> with
1> [
1> _OutputIt=fmt::v8::appender,
1> OutputIt=fmt::v8::appender
1> ]
1>foo.cpp(39): note: while trying to match the argument list '(OutputIt, const char [17], const double, const double)'
1> with
1> [
1> OutputIt=fmt::v8::appender
1> ]
1>fmt-src\include\fmt\core.h(1266): note: see reference to function template instantiation 'OutputIt fmt::v8::formatter<point,char,void>::format<Context>(const point &,FormatContext &)' being compiled
1> with
1> [
1> OutputIt=fmt::v8::appender,
1> Context=fmt::v8::format_context,
1> FormatContext=fmt::v8::format_context
1> ]
1>fmt-src\include\fmt\core.h(1249): note: see reference to function template instantiation 'void fmt::v8::detail::value<Context>::format_custom_arg<value_type,fmt::v8::formatter<point,char,void>>(void *,fmt::v8::basic_format_parse_context<char,fmt::v8::detail::error_handler> &,Context &)' being compiled
1> with
1> [
1> Context=fmt::v8::format_context
1> ]
1>fmt-src\include\fmt\core.h(1245): note: see reference to function template instantiation 'void fmt::v8::detail::value<Context>::format_custom_arg<value_type,fmt::v8::formatter<point,char,void>>(void *,fmt::v8::basic_format_parse_context<char,fmt::v8::detail::error_handler> &,Context &)' being compiled
1> with
1> [
1> Context=fmt::v8::format_context
1> ]
1>fmt-src\include\fmt\core.h(1728): note: see reference to function template instantiation 'fmt::v8::detail::value<Context>::value<const point>(T &)' being compiled
1> with
1> [
1> Context=fmt::v8::format_context,
1> T=const point
1> ]
1>fmt-src\include\fmt\core.h(1728): note: see reference to function template instantiation 'fmt::v8::detail::value<Context>::value<const point>(T &)' being compiled
1> with
1> [
1> Context=fmt::v8::format_context,
1> T=const point
1> ]
1>fmt-src\include\fmt\core.h(1744): note: see reference to function template instantiation 'fmt::v8::detail::value<Context> fmt::v8::detail::make_value<Context,point&>(T)' being compiled
1> with
1> [
1> Context=fmt::v8::format_context,
1> T=point &
1> ]
1>fmt-src\include\fmt\core.h(1863): note: see reference to function template instantiation 'fmt::v8::detail::value<Context> fmt::v8::detail::make_arg<true,Context,fmt::v8::detail::type::custom_type,point&,0>(T)' being compiled
1> with
1> [
1> Context=fmt::v8::format_context,
1> T=point &
1> ]
1>fmt-src\include\fmt\core.h(1886): note: see reference to function template instantiation 'fmt::v8::format_arg_store<fmt::v8::format_context,point>::format_arg_store<point&>(point &)' being compiled
1>fmt-src\include\fmt\core.h(1886): note: see reference to function template instantiation 'fmt::v8::format_arg_store<fmt::v8::format_context,point>::format_arg_store<point&>(point &)' being compiled
1>fmt-src\include\fmt\core.h(3263): note: see reference to function template instantiation 'fmt::v8::format_arg_store<fmt::v8::format_context,point> fmt::v8::make_format_args<fmt::v8::format_context,point&>(point &)' being compiled
1>foo.cpp(50): note: see reference to function template instantiation 'void fmt::v8::print<point&>(fmt::v8::basic_format_string<char,point &>,point &)' being compiled
1>foo.cpp(43): error C2668: 'fmt::v8::format_to': ambiguous call to overloaded function
1>fmt-src\include\fmt\core.h(3203): note: could be '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 &)'
1> with
1> [
1> OutputIt=fmt::v8::appender
1> ]
1>C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.32.31326\include\format(3046): note: or '_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]
1> with
1> [
1> _OutputIt=fmt::v8::appender,
1> OutputIt=fmt::v8::appender
1> ]
1>foo.cpp(39): note: while trying to match the argument list '(OutputIt, const char [17], const double, const double)'
1> with
1> [
1> OutputIt=fmt::v8::appender
1> ]
1>Done building project "foo.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Build time 00:01:753
Build ended at 15/05/2022 19.35.20
After updating Visual Studio Professional 2022 to version 17.2.0 (compiler version 19.32.31328 for x64), Formatting User-defined Types example no longer compiles.
This might be a bug in Visual Studio, but would still be good to have a work around.
In order to trigger the issue,
<mutex>must be included.I could not repro with compiler explorer, it might not have this compiler version of yet.
Compiler output: