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

Types with implicit user conversion to number are incorrectly printed when FMT_COMPILE is in use. #2565

Closed
PiotrZSL opened this issue Oct 25, 2021 · 2 comments

Comments

@PiotrZSL
Copy link

Problematic code:

#include <fmt/core.h>
#include <fmt/compile.h>
#include <fmt/ostream.h>
#include <boost/serialization/strong_typedef.hpp>

BOOST_STRONG_TYPEDEF(std::uint32_t, SomeMagicStrongType)

struct TypeWithCast
{
   operator const std::uint32_t&() const {
    return t;
  }
  operator std::uint32_t&() {
    return t;
  }

  std::uint32_t t = 'A';
};

int main() {
  SomeMagicStrongType value{50u};
  std::string s = fmt::format(FMT_COMPILE("Value of strongtype is {} and custom type is {}."), value, TypeWithCast());
  fmt::print("{}", s);
}

Output when FMT_COMPILE is used:
Value of strongtype is 2 and custom type is A.

Output when FMT_COMPILE is not used:
Value of strongtype is 50 and custom type is 65.

This is a break of backward compatibility.

@alexezeder
Copy link
Contributor

alexezeder commented Oct 26, 2021

Actually, this problem is caused not by compile-time API but by underlying calls - https://godbolt.org/z/bjGheazrG.

This is a break of backward compatibility.

More importantly, this was done in 7.0 version of {fmt} 😄 - https://godbolt.org/z/GExb3rY5c.

In the current version, this write() overload is invoked:

fmt/include/fmt/format.h

Lines 2109 to 2114 in df40e94

template <typename Char, typename OutputIt>
FMT_CONSTEXPR auto write(OutputIt out, Char value) -> OutputIt {
auto it = reserve(out, 1);
*it++ = value;
return base_iterator(out, it);
}

But this is happening only because mapped_type_constant (arg_mapper-based check) is not type::custom_type for the type with such conversion operator. But it is type::custom_type for types with conversion operators other than const-reference one.

And that's all from me, at least for today, since I have no idea how to make mapped_type_constant return type::custom_type for this type.

@vitaut
Copy link
Contributor

vitaut commented Oct 31, 2021

Fixed in 028f227, thanks for reporting.

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