gpt4 book ai didi

c++ - 为自定义类型实现格式化程序时如何有效地转发格式化参数

转载 作者:行者123 更新时间:2023-12-04 07:54:57 25 4
gpt4 key购买 nike

我正在尝试编写一个自定义格式化程序来帮助我打印 vector 。我试图维护格式说明符,以便 vector 中的每个项目都以相同的方式格式化。
我的大部分灵感来自 this tutorial , 和 the docs

#include <fmt/core.h>
#include <fmt/format.h>

template<typename ValueType>
struct fmt::formatter<std::vector<ValueType>> : fmt::formatter<ValueType>
{
std::string formatString;

// Hack, copy the original format text into a std::string
constexpr auto parse(format_parse_context& ctx)
{
formatString= "{:";
for (auto iter = std::begin(ctx); iter != std::end(ctx); ++iter) {
char c = *iter;{
formatString += c;
}
if (c == '}') {
return iter;
}
}
return std::end(ctx);
}

template <typename FormatContext>
auto format(const std::vector<ValueType>& container, FormatContext& context)
{
auto&& out = context.out();
format_to(out, "{{");

typename std::vector<ValueType>::size_type count = 0;
const typename std::vector<ValueType>::size_type size = container.size();
for (const auto& item : container) {
// Use the copied format string, but really want to delegate the formatting to superclass...
format_to(out, formatString, item);
if (++count < size) {
format_to(out, ", ");
}
}

return format_to(out, "}}");
}
};

int main()
{
fmt::print("{:.3f}\n", std::vector{ 0.0, 321.123, 654398.4328, -0.0000000000012345, 2374651273.7236457862345});
fmt::print("{:.1e}\n", std::vector{ 0.0, 321.123, 654398.4328, -0.0000000000012345, 2374651273.7236457862345});
return 0;
}
哪些输出:
{0.000, 321.123, 654398.433, -0.000, 2374651273.724}
{0.0e+00, 3.2e+02, 6.5e+05, -1.2e-12, 2.4e+09}
复制格式字符串似乎过于笨拙且效率低下,以便我可以将其反馈给另一个 fmt::format调用,特别是当扩展类 : fmt::formatter<ValueType>已经为我们提供了一个完全有效的 parse内部函数,(我在这个例子中重新实现了它只是为了以一种hacky的方式获得所需的输出)。
我真的想删除自定义解析实现并替换该行
format_to(out, formatString, item);
format_to(out, fmt::formatter<ValueType>::format(item, context))
除非它无效/无法编译。
这样做的正确方法是什么?

注意:我完全意识到在我的例子中扩展类型是毫无意义的,我可以将它作为局部变量但是我试图重用类的功能,所以扩展它感觉是正确的方向,即使我还没有找到解决方案。

我发现的所有其他示例的列表还没有帮助我:
  • String formatting the cool way with C++20 std::format() (仅适用于直接返回对 super 实现的单个调用,但不需要重新实现解析或创建新的格式字符串)
  • Custom format specifier with {fmt} for custom class (放弃格式化或需要手动重新实现格式化)
  • The tutorial I mostly copied (几乎是我想要的,但仍然创建一个新的格式字符串,而不是重用用户最初指定的格式)
  • The Docs (同样,要么建议重新实现解析函数并使用新的格式字符串调用 format,尽管调用者已经指定了一个并且该类型已有解析函数...)
  • 最佳答案

    你可以摆脱你的parse实现并使用继承的函数,并使用fmt::formatter<ValueType>::format(item, context)在您的 format 内输出每个项目( godbolt demo ):

    #include <fmt/core.h>
    #include <fmt/format.h>

    template<typename ValueType>
    struct fmt::formatter<std::vector<ValueType>> : fmt::formatter<ValueType>
    {
    template <typename FormatContext>
    auto format(const std::vector<ValueType>& container, FormatContext& context)
    {
    auto&& out = context.out();
    format_to(out, "{{");

    bool first = true;
    for (const auto& item : container) {
    if (first) {
    first = false;
    } else {
    format_to(out, ", ");
    }
    fmt::formatter<ValueType>::format(item, context);
    }

    return format_to(out, "}}");
    }
    };

    int main()
    {
    fmt::print("{:.3f}\n", std::vector{ 0.0, 321.123, 654398.4328, -0.0000000000012345, 2374651273.7236457862345});
    fmt::print("{:.1e}\n", std::vector{ 0.0, 321.123, 654398.4328, -0.0000000000012345, 2374651273.7236457862345});
    return 0;
    }

    您可以在 Formatting User-defined Types 下的文档中看到此模式的其他示例。 .

    关于c++ - 为自定义类型实现格式化程序时如何有效地转发格式化参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66752337/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com