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

#include <fmt/ranges.h> breaks formatting Eigen types #4058

Closed
TobiSchluter opened this issue Jul 8, 2024 · 3 comments
Closed

#include <fmt/ranges.h> breaks formatting Eigen types #4058

TobiSchluter opened this issue Jul 8, 2024 · 3 comments
Labels

Comments

@TobiSchluter
Copy link
Contributor

TobiSchluter commented Jul 8, 2024

Unlike previous versions, fmt 11.0 requires including fmt/ranges.h in order to use fmt::join. But including fmt/ranges.h breaks formatting Eigen types. This happens already in fmt 10.2.1, and maybe earlier versions, but since I could use fmt::join without #include <fmt/ranges.h> before, I didn't run into this problem. In that sense this is an incompatible change.

https://godbolt.org/z/Tz3bKWrMK

#include <Eigen/Dense>
#include <fmt/format.h>
#include <fmt/ostream.h>
#ifdef INCLUDE_RANGES // defining this breaks the compile.
#  include <fmt/ranges.h>
#endif

template<typename T>
struct fmt::formatter<T,
    std::enable_if_t<
        std::is_base_of_v<
            Eigen::EigenBase<T>, T>, char>>
    : fmt::ostream_formatter
{};

int main()
{
    Eigen::Vector3d v;
    fmt::print("{}\n", v.transpose());
}
@vitaut
Copy link
Contributor

vitaut commented Jul 8, 2024

This is expected. If you provide a formatter for a range type you need to opt it out of range formatting rather than fiddle with includes: https://godbolt.org/z/3ercdas5z.

@vitaut vitaut closed this as completed Jul 8, 2024
@TobiSchluter
Copy link
Contributor Author

TobiSchluter commented Jul 8, 2024

Thanks for the quick reply! Not that I would have expected this to be a range type, at least not a general matrix, but I'm aware that Eigen makes some unorthodox choices WRT iterators.

@TobiSchluter
Copy link
Contributor Author

TobiSchluter commented Jul 8, 2024

Here's what I settled on and placed next to the formatter. Maybe this is useful for someone who stumbles on this problem. Compared to Victor's version, it works also when not including ranges.h. The namespace macros are used to get the correctly versioned inline namespace. I'm using false_type because static constexpr const is a bit much for me to process :)

// Need to opt out of range formatting which id's Eigen::Matrix types as ranges if fmt/ranges.h is included.
FMT_BEGIN_NAMESPACE
    // Forward declaration in case fmt/ranges.h is not included.
    template <typename T, typename Char> struct is_range;

    // ... and the opt-out.
    template <typename T>
    struct is_range<T,
        std::enable_if_t<std::is_base_of_v<Eigen::EigenBase<T>, T>, char>>
        : std::false_type
    {};
FMT_END_NAMESPACE

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

No branches or pull requests

2 participants