Git Product home page Git Product logo

Comments (8)

gregmarr avatar gregmarr commented on June 9, 2024

User-defined types must opt in to being formatted by std::format by specializing std::formatter. https://en.cppreference.com/w/cpp/utility/format/formatter

fmt::format is probably picking up implicit conversions, which means that it can get them very very wrong. What happens if you have a json file with numbers instead of strings? Does fmt::format display them properly? I would be very surprised, unless someone added support for this specific library.

I assume that std::format explicitly excludes implicit conversions to types that std::formatter is enabled for, which is much safer.

from json.

AA1999 avatar AA1999 commented on June 9, 2024

For some reason now fmt is also now not working (I'm pretty sure it did before, maybe an earlier version)

In file included from test.cpp:4:
In file included from /usr/include/fmt/format.h:49:
/usr/include/fmt/core.h:2548:45: error: implicit instantiation of undefined template 'fmt::detail::type_is_unformattable_for<nlohmann::basic_json<>, char>'
    type_is_unformattable_for<T, char_type> _;
                                            ^
/usr/include/fmt/core.h:2611:23: note: in instantiation of function template specialization 'fmt::detail::parse_format_specs<nlohmann::basic_json<>, fmt::detail::compile_parse_context<char>>' requested here
        parse_funcs_{&parse_format_specs<Args, parse_context_type>...} {}
                      ^
/usr/include/fmt/core.h:2740:47: note: in instantiation of member function 'fmt::detail::format_string_checker<char, nlohmann::basic_json<>, nlohmann::basic_json<>>::format_string_checker' requested here
      detail::parse_format_string<true>(str_, checker(s));
                                              ^
test.cpp:9:27: note: in instantiation of function template specialization 'fmt::basic_format_string<char, nlohmann::basic_json<> &, nlohmann::basic_json<> &>::basic_format_string<char[6], 0>' requested here
        std::cout << fmt::format("{} {}", data.at("host"), data.at("port"));
                                 ^
/usr/include/fmt/core.h:1554:45: note: template is declared here
template <typename T, typename Char> struct type_is_unformattable_for;
                                            ^
test.cpp:9:27: error: call to consteval function 'fmt::basic_format_string<char, nlohmann::basic_json<> &, nlohmann::basic_json<> &>::basic_format_string<char[6], 0>' is not a constant expression
        std::cout << fmt::format("{} {}", data.at("host"), data.at("port"));
                                 ^
In file included from test.cpp:4:
In file included from /usr/include/fmt/format.h:49:
/usr/include/fmt/core.h:1576:63: error: implicit instantiation of undefined template 'fmt::detail::type_is_unformattable_for<nlohmann::basic_json<>, char>'
    type_is_unformattable_for<T, typename Context::char_type> _;
                                                              ^
/usr/include/fmt/core.h:1808:23: note: in instantiation of function template specialization 'fmt::detail::make_arg<true, fmt::basic_format_context<fmt::appender, char>, nlohmann::basic_json<>, 0>' requested here
        data_{detail::make_arg<is_packed, Context>(args)...} {
                      ^
/usr/include/fmt/core.h:1826:10: note: in instantiation of function template specialization 'fmt::format_arg_store<fmt::basic_format_context<fmt::appender, char>, nlohmann::basic_json<>, nlohmann::basic_json<>>::format_arg_store<nlohmann::basic_json<>, nlohmann::basic_json<>>' requested here
  return {args...};
         ^
/usr/include/fmt/core.h:2788:28: note: in instantiation of function template specialization 'fmt::make_format_args<fmt::basic_format_context<fmt::appender, char>, nlohmann::basic_json<>, nlohmann::basic_json<>>' requested here
  return vformat(fmt, fmt::make_format_args(args...));
                           ^
test.cpp:9:20: note: in instantiation of function template specialization 'fmt::format<nlohmann::basic_json<> &, nlohmann::basic_json<> &>' requested here
        std::cout << fmt::format("{} {}", data.at("host"), data.at("port"));
                          ^
/usr/include/fmt/core.h:1554:45: note: template is declared here
template <typename T, typename Char> struct type_is_unformattable_for;
                                            ^
/usr/include/fmt/core.h:1579:3: error: static assertion failed due to requirement 'formattable': Cannot format an argument. To make type T formattable provide a formatter<T> specialization: https://fmt.dev/latest/api.html#udt
  static_assert(
  ^
4 errors generated.

Anyhow then ig nlohmann::json would need a std::formatter?

from json.

gregmarr avatar gregmarr commented on June 9, 2024

Anyhow then ig nlohmann::json would need a std::formatter?

Yes. I assume, but can't say for sure, that a PR would be welcome as long as it was sufficient protected such that it didn't affect the ability to build as C++11. There are other features that are conditionally available based on the C++ standard in use. @nlohmann would have the final say on that.

from json.

AA1999 avatar AA1999 commented on June 9, 2024

As far as I'm aware there are micros to check C++ version and not define a function if it's not matching, so maybe this could be added only if c++20 flag is added.

from json.

gregmarr avatar gregmarr commented on June 9, 2024

Yes, this library has JSON_HAS_CPP_20 for that.

from json.

heinemml avatar heinemml commented on June 9, 2024

I ran into this when updating dependencies.

For fmt you can observe this break in this godbolt example: https://godbolt.org/z/jx7fTen7Y

with fmt 9.1.0 it works, with 10.0.0 it still compiles but throws and with 10.1.1 it finally doesn't compile anymore.

I guess something like this would fix the issue for std::format

#if defined(JSON_HAS_CPP_20) && __has_include(<format>)

#include <format>

template <>
struct std::formatter<json> {

    constexpr auto parse(std::format_parse_context& ctx) {
        return ctx.begin();
    }

    auto format(const json& j, std::format_context& ctx) const {
        return std::format_to(ctx.out(), "{}", to_string(j));
    }
};

#endif

but this doesn't fix it for fmt :(.

from json.

heinemml avatar heinemml commented on June 9, 2024

fmtlib/fmt#3648

from json.

heinemml avatar heinemml commented on June 9, 2024

To implement a formatter which would work from fmt 10.0.0 onwards it would suffice to implement format_as as follows:

namespace nlohmann {

auto format_as(const json& j) { return j.dump(); }

}

Godbolt: https://godbolt.org/z/vEEad83h3

from json.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.