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

Compilation issue of fmt::format's example #2601

Closed
laper32 opened this issue Nov 14, 2021 · 2 comments
Closed

Compilation issue of fmt::format's example #2601

laper32 opened this issue Nov 14, 2021 · 2 comments

Comments

@laper32
Copy link

laper32 commented Nov 14, 2021

Compiler: MSVC 17.0.0 (Visual Studio 2022)
C++ Version: 20
fmt version: latest git clone

The exactly line of error has been marked at the source code below.
You can check the comment to find it.

Source code:

This comes from https://fmt.dev/latest/api.html#formatting-user-defined-types

#include <fmt/core.h>
#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 format_to(
			ctx.out(),
			presentation == 'f' ? "({:.1f}, {:.1f})" : "({:.1e}, {:.1e})", // All errors are come from here.
			p.x, p.y);
	}
};
int main() {
	point p = { 1, 2 };
	std::string s = fmt::format("{:f}", p);
}

Error message:

D:\workshop\cxx\CommonLab\main.cpp(345): error C7595: 'fmt::v8::basic_format_string<char,const double &,const double &>::basic_format_string': call to immediate function is not a constant expression
  D:\workshop\cxx\CommonLab\main.cpp(345): note: failure was caused by a read of a variable outside its lifetime
  D:\workshop\cxx\CommonLab\main.cpp(345): note: see usage of 'this'
  D:\workshop\cxx\CommonLab\fmt\include\fmt/core.h(1242): note: see reference to function template instantiation 'OutputIt fmt::v8::formatter<point,char,void>::format<Context>(const point &,FormatContext &)' being compiled
          with
          [
              OutputIt=fmt::v8::appender,
              Context=context,
              FormatContext=context
          ]
  D:\workshop\cxx\CommonLab\fmt\include\fmt/core.h(1225): 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
          with
          [
              Context=fmt::v8::format_context
          ]
  D:\workshop\cxx\CommonLab\fmt\include\fmt/core.h(1221): 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
          with
          [
              Context=fmt::v8::format_context
          ]
  D:\workshop\cxx\CommonLab\fmt\include\fmt/core.h(1686): note: see reference to function template instantiation 'fmt::v8::detail::value<Context>::value<const point>(T &)' being compiled
          with
          [
              Context=fmt::v8::format_context,
              T=const point
          ]
  D:\workshop\cxx\CommonLab\fmt\include\fmt/core.h(1686): note: see reference to function template instantiation 'fmt::v8::detail::value<Context>::value<const point>(T &)' being compiled
          with
          [
              Context=fmt::v8::format_context,
              T=const point
          ]
  D:\workshop\cxx\CommonLab\fmt\include\fmt/core.h(1804): 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
          with
          [
              Context=fmt::v8::format_context,
              T=point &
          ]
  D:\workshop\cxx\CommonLab\fmt\include\fmt/core.h(1827): note: see reference to function template instantiation 'fmt::v8::format_arg_store<fmt::v8::format_context,point>::format_arg_store<point&>(point &)' being compiled
  D:\workshop\cxx\CommonLab\fmt\include\fmt/core.h(1827): note: see reference to function template instantiation 'fmt::v8::format_arg_store<fmt::v8::format_context,point>::format_arg_store<point&>(point &)' being compiled
  D:\workshop\cxx\CommonLab\fmt\include\fmt/core.h(3071): 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
  D:\workshop\cxx\CommonLab\main.cpp(352): note: see reference to function template instantiation 'std::string fmt::v8::format<point&>(fmt::v8::basic_format_string<char,point &>,point &)' being compiled

Note: Looks like this example marked as problem many times, perhaps this example need also write into test cases.

@laper32
Copy link
Author

laper32 commented Nov 14, 2021

Similar issues:
#2574
#2522

@vitaut
Copy link
Contributor

vitaut commented Nov 14, 2021

Those are not similar issues but exactly the same (fixed) issue. Please see the dev docs: https://fmt.dev/dev/api.html#formatting-user-defined-types.

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

No branches or pull requests

2 participants