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

user types + operator<< fails if there's also an operator bool() #1766

Closed
lgritz opened this issue Jul 10, 2020 · 6 comments
Closed

user types + operator<< fails if there's also an operator bool() #1766

lgritz opened this issue Jul 10, 2020 · 6 comments

Comments

@lgritz
Copy link

lgritz commented Jul 10, 2020

I had a user type (let's call it Type) that defined an operator<<.

The magic of ostream.h caused this to work as expected for both new format and old sprintf style formatting:

Type t;
fmt::format("{}", t);
fmt::sprintf("%s", t);

through 6.1.2. But starting with 6.2+, it would render the Type as "true" or "false."

Aha, it turns out that this is because my Type also has an operator bool() which fmt was seeming to use to infer printing it as a bool, rather than falling back to the operator<<. (For <= 6.1.2, the operator bool() didn't confuse it, it always used the operator<< as expected.)

I tried defining a template <> struct fmt::formatter<Type>, the preferred method when not using operator<<. And this works... for fmt::format(), but does not seem to help printf/sprintf in any way, where %s still is confused and renders the type as if it were a bool.

@vitaut
Copy link
Contributor

vitaut commented Jul 12, 2020

Should be fixed in 16cac46, thanks for reporting.

@vitaut vitaut closed this as completed Jul 12, 2020
@lgritz
Copy link
Author

lgritz commented Jul 12, 2020

Thanks!

And once again, thanks for such a great package, all my projects depend on this heavily.

@lgritz
Copy link
Author

lgritz commented Jul 29, 2020

Hi, was there a reason that this fix was not included in 7.0.2?

@vitaut
Copy link
Contributor

vitaut commented Jul 29, 2020

It's a more significant change and will be included in the next minor, not patch release.

@lgritz
Copy link
Author

lgritz commented Jul 29, 2020

ok, thanks

@Boddlnagg
Copy link

This change also fixed the following issue that I had:

When I added the following code to test/ostream-test.cc, I would get a static assertion error in the second line:

static_assert(fmt::detail::type_constant<decltype(fmt::detail::arg_mapper<fmt::buffer_context<char>>().map(std::declval<const unstreamable_enum&>())),
                  typename fmt::buffer_context<char>::char_type>::value == fmt::detail::type::uint_type, "wrong arg type");
static_assert(fmt::detail::type_constant<decltype(fmt::detail::arg_mapper<fmt::buffer_context<wchar_t>>().map(std::declval<const unstreamable_enum&>())),
                  typename fmt::buffer_context<wchar_t>::char_type>::value == fmt::detail::type::uint_type, "wrong arg type");

I.e., unstreamable_enum is recognized as a custom type, even though it should just be formatted as the underlying integer type, but only when formatting as wchar_t, not for char.

For me this led to a segfault at runtime, because the argument was of type custom_type but its value was simply the underlying integer value. Trying to interpret that integer value as a custom format pointer would then fail.

This was kind of hard to analyze, because I wasn't even using the operator<< support, but only included fmt/printf.h, which transitively includes fmt/ostream.h, which triggers this problem.

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

3 participants