fmt:来自 lambda 的自定义就地格式化程序

问题描述 投票:0回答:1

我有点不喜欢 fmt(及其

std
变体)的现有 API 来为不同类型自定义格式化程序:

  1. 我期望有一种更传统的方法来提供就地 lambda。
  2. 一种类型只能有一个模板特化。
  3. 专业化只能在其自己的命名空间中声明(不能在
    std::formatter
    命名空间内专业化
    foo
  4. 不可能专门化本地或未命名类型

也许我错过了一些东西,但编写临时解决方案比找到预期的解决方案更容易(如果有的话......)。
下面是一个工作示例,但我很高兴看到更干净的示例。

c++ formatting fmt
1个回答
0
投票

使用包装器模板的最简单且幼稚的解决方案。 Lambda 保证具有唯一的类型,因此有无数种方法可以格式化一种类型。
我这里没有提供

parse
接口,因为我认为它相当多余。
不过还没有尝试过数组。

#include <format>

template <typename T, typename Format>
struct in_place_formatter{
    const T &value;
    Format format;
};

template <typename T, typename Format>
in_place_formatter(const T&, Format) -> in_place_formatter<T, Format>;

template <typename T, typename Format, typename Char>
struct std::formatter<in_place_formatter<T, Format>, Char> {
    constexpr auto parse(std::format_parse_context &ctx) { return ctx.begin(); }
    constexpr auto format(const in_place_formatter<T, Format> &uf, std::format_context &ctx) const {
        return uf.format(uf.value, ctx);
    }
};


#include <iostream>

int main() {
    struct {} john_cena;
    std::cout << std::format("And his name is... {}\n", 
        in_place_formatter{john_cena, 
            [](const auto&, std::format_context &ctx)
            {
                return std::format_to(ctx.out(), "{}", "John Cena");
            }});

    std::cout << std::format("{}\n", 
        in_place_formatter{john_cena, 
            [](const auto&, std::format_context &ctx)
            {
                return std::format_to(ctx.out(), "{}", "You can't see me");
            }});

    return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.