我正在尝试使用 c++20 格式而不是 Eigen::IOFormat 打印 Eigen::Array 或 Eigen::Matrix。 我想用说明符控制矩阵中元素的精度和对齐方式,例如,
#include <Eigen/Core>
#include <format>
#include <iostream>
int main()
{
Eigen::ArrayXXd mat( 3, 4 );
mat.setZero();
std::cout << std::format( "mat={:9.4f}\n", mat );
return 0;
}
怎样才能得到下面的预期结果?
mat= 0.0000 0.0000 0.0000 0.0000
0.0000 0.0000 0.0000 0.0000
0.0000 0.0000 0.0000 0.0000
您可以查看https://gite.lirmm.fr/rpc/utils/eigen-fmt,看看它是否对您有帮助。
您基本上需要包含 这个头文件,以便使用
fmt
库获得对打印/格式的特征支持。由于 std::format
是基于 fmt
的,因此该代码应该是一个良好的开始,以实现您想要的目标。请注意,您可能需要进行一些调整。
我使用基于对我有用的概念的解决方案。到目前为止已使用 Visual Studio 2022 进行了测试。
#include <string>
#include <iostream>
#include <format>
#include <Eigen/Eigen>
template <typename EigenExprTypeT>
concept EigenTypeMatExpr = requires(const EigenExprTypeT t) {
std::remove_cvref_t<EigenExprTypeT>::RowsAtCompileTime;
std::remove_cvref_t<EigenExprTypeT>::ColsAtCompileTime;
typename std::remove_cvref_t<EigenExprTypeT>::Scalar;
{
t.size()
} -> std::same_as<typename Eigen::Index>;
{
t.rows()
} -> std::same_as<typename Eigen::Index>;
{
t.cols()
} -> std::same_as<typename Eigen::Index>;
};
enum class EigenCustomFormats {
Default, //
CleanFormat, // cf
HeavyFormat, // hf
SingleLineFormat, // sfl
HighPrecisionFormat, // hpf
DebuggingFormat // df
};
static const auto defaultFormat = Eigen::IOFormat();
static const auto cleanFormat = Eigen::IOFormat(4, 0, ", ", "\n", "[", "]");
static const auto heavyFormat = Eigen::IOFormat(Eigen::FullPrecision, 0, ", ", ";\n", "[", "]", "[", "]");
static const auto singleLineFormat =
Eigen::IOFormat(Eigen::StreamPrecision, Eigen::DontAlignCols, ", ", ", ", "", "", "", "");
static const auto highPrecisionFormat =
Eigen::IOFormat(Eigen::FullPrecision, Eigen::DontAlignCols, " ", "\n", "", "", "", "");
static const auto debuggingFormat =
Eigen::IOFormat(Eigen::FullPrecision, Eigen::DontAlignCols, " ", "\n", "", "", "\n", "");
template <EigenTypeMatExpr MatT>
struct std::formatter<MatT> {
constexpr auto parse(format_parse_context& ctx) {
const std::string_view fmt(ctx.begin(), ctx.end());
if (fmt.starts_with("cf"))
_format = EigenCustomFormats::CleanFormat;
if (fmt.starts_with("hf"))
_format = EigenCustomFormats::HeavyFormat;
if (fmt.starts_with("sfl"))
_format = EigenCustomFormats::SingleLineFormat;
if (fmt.starts_with("hpf"))
_format = EigenCustomFormats::HighPrecisionFormat;
if (fmt.starts_with("df"))
_format = EigenCustomFormats::DebuggingFormat;
return ctx.begin() + fmt.find_first_of('}');
}
// Format the type for output
template <typename FormatContext>
auto format(const MatT& m, FormatContext& ctx) const {
switch (_format) {
case EigenCustomFormats::CleanFormat: return std::format_to(ctx.out(), "{}", (std::stringstream{} << std::fixed << m.format(cleanFormat)).str());
case EigenCustomFormats::HeavyFormat: return std::format_to(ctx.out(), "{}", (std::stringstream{} << std::fixed << m.format(heavyFormat)).str());
case EigenCustomFormats::SingleLineFormat: return std::format_to(ctx.out(), "{}", (std::stringstream{} << std::fixed << m.format(singleLineFormat)).str());
case EigenCustomFormats::HighPrecisionFormat: return std::format_to(ctx.out(), "{}", (std::stringstream{} << std::fixed << m.format(highPrecisionFormat)).str());
case EigenCustomFormats::DebuggingFormat: return std::format_to(ctx.out(), "{}", (std::stringstream{} << std::fixed << m.format(debuggingFormat)).str());
default: return std::format_to(ctx.out(), "{}", (std::stringstream{} << std::fixed << m.format(defaultFormat)).str());
}
}
private:
EigenCustomFormats _format{ EigenCustomFormats::Default };
};
template <EigenTypeMatExpr MatT>
std::ostream& operator<<(std::ostream& os, const MatT& mat)
{
return os << std::format("{:hf}", mat);
}
int main()
{
Eigen::Matrix2f m = Eigen::Matrix2f::Random();
std::cout << Eigen::Matrix2f::Random() << std::endl << std::endl << std::endl;
std::cout << std::format("{}\n", Eigen::Matrix2f::Random()) << std::endl;
std::cout << std::format("{:cf}\n", Eigen::Matrix2f::Random()) << std::endl;
std::cout << std::format("{:hf}\n", Eigen::Matrix2f::Random()) << std::endl;
std::cout << std::format("{:sfl}\n", Eigen::Matrix2f::Random()) << std::endl;
std::cout << std::format("{:hpf}\n", Eigen::Matrix2f::Random()) << std::endl;
std::cout << std::format("{:df}\n", Eigen::Matrix2f::Random()) << std::endl;
return 0;
}