Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

format conflict with Visual Studio 2022 17.2.0 #2896

Closed
tksuoran opened this issue May 15, 2022 · 2 comments
Closed

format conflict with Visual Studio 2022 17.2.0 #2896

tksuoran opened this issue May 15, 2022 · 2 comments

Comments

@tksuoran
Copy link

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.

#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;
}

Compiler output:

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
@vitaut
Copy link
Contributor

vitaut commented May 15, 2022

Added namespace qualification to the example: 5ab9d39. Thanks for reporting.

@vitaut vitaut closed this as completed May 15, 2022
@tksuoran
Copy link
Author

Wow that was a fast fix. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants