eigen3 与 libfmt >= 9.0

2023-12-26

我曾经能够将 Eigen3 数组/矩阵传递给 spdlog,它内部使用 libfmt。从 libfmt 9.0.0 开始,这些类型不再由 libfmt 格式化,无需进一步的代码。

fmt 通过专门化支持自定义类型fmt::formatter<T>对于类型;fmt9 文档 https://fmt.dev/9.0.0/api.html#std-ostream-support进一步解释说,这种专业化源于ostream_formatter将利用现有的operator<<,本征类可以方便地提供。

Eigen 使用CRTP继承 https://eigen.tuxfamily.org/dox/TopicClassHierarchy.html我会专门为所有人Eigen::DenseBase<T>像这样的类型:

#include<fmt/ostream.h>
#include<eigen3/Eigen/Core>
#include<iostream>

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

int main(){
    Eigen::Array3f a(1,2,3);
    std::cout<<fmt::format("{}",a)<<std::endl;
}

自从我发帖以来,很明显这并不顺利:

In file included from /usr/include/fmt/format.h:48,
                 from /usr/include/fmt/ostream.h:18,
                 from /tmp/aa.cpp:1:
/usr/include/fmt/core.h: In instantiation of ‘constexpr fmt::v9::detail::value<Context> fmt::v9::detail::make_value(T&&) [with Context = fmt::v9::basic_format_context<fmt::v9::appender, char>; T = Eigen::Array<float, 3, 1>&]’:
/usr/include/fmt/core.h:1771:29:   required from ‘constexpr fmt::v9::detail::value<Context> fmt::v9::detail::make_arg(T&&) [with bool IS_PACKED = true; Context = fmt::v9::basic_format_context<fmt::v9::appender, char>; fmt::v9::detail::type <anonymous> = fmt::v9::detail::type::custom_type; T = Eigen::Array<float, 3, 1>&; typename std::enable_if<IS_PACKED, int>::type <anonymous> = 0]’
/usr/include/fmt/core.h:1895:77:   required from ‘constexpr fmt::v9::format_arg_store<Context, Args>::format_arg_store(T&& ...) [with T = {Eigen::Array<float, 3, 1, 0, 3, 1>&}; Context = fmt::v9::basic_format_context<fmt::v9::appender, char>; Args = {Eigen::Array<float, 3, 1, 0, 3, 1>}]’
/usr/include/fmt/core.h:1912:31:   required from ‘constexpr fmt::v9::format_arg_store<Context, typename std::remove_cv<typename std::remove_reference<Args>::type>::type ...> fmt::v9::make_format_args(Args&& ...) [with Context = fmt::v9::basic_format_context<fmt::v9::appender, char>; Args = {Eigen::Array<float, 3, 1, 0, 3, 1>&}]’
/usr/include/fmt/core.h:3184:44:   required from ‘std::string fmt::v9::format(fmt::v9::format_string<T ...>, T&& ...) [with T = {Eigen::Array<float, 3, 1, 0, 3, 1>&}; std::string = std::__cxx11::basic_string<char>; fmt::v9::format_string<T ...> = fmt::v9::basic_format_string<char, Eigen::Array<float, 3, 1, 0, 3, 1>&>]’
/tmp/aa.cpp:7:24:   required from here
/usr/include/fmt/core.h:1751:7: error: static assertion failed: Cannot format an argument. To make type T formattable provide a formatter<T> specialization: https://fmt.dev/latest/api.html#udt
 1751 |       formattable,
      |       ^~~~~~~~~~~
/usr/include/fmt/core.h:1751:7: note: ‘formattable’ evaluates to false

我可以获得一些如何正确执行此操作的解释吗?我想既了解这里 C++ 的情况,又想有一个基于此的可行解决方案。谢谢!


如果你有 c++20,你也可以使用一个概念,它可以防止陷入这个 SFINAE / void 陷阱:

template <typename T>
    requires std::is_base_of_v<Eigen::DenseBase<T>, T>
struct fmt::formatter<T> : ostream_formatter {};

https://godbolt.org/z/WGG77vGEr https://godbolt.org/z/WGG77vGEr

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

eigen3 与 libfmt >= 9.0 的相关文章

随机推荐