You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为fmt库添加格式说明符实现整数十六进制与十进制双输出?

为fmt库添加整数双格式(十六进制+十进制)的格式说明符

希望为fmt库添加一个格式说明符,让整数同时以十六进制和十进制形式输出(例如"0xff (255)")。尝试通过自定义整数别名myint = uint64_t并特化fmt::formatter的方法失败,代码如下:

using myint = uint64_t;
template <> struct fmt::formatter<myint> {
  constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) {
    auto it = ctx.begin(), end = ctx.end();
    if(it != end && *it == 'z')
        it++;
    return it;
  }

  template <typename FormatContext>
  auto format(const myint& p, FormatContext& ctx) const -> decltype(ctx.out()) {
      return fmt::format_to(ctx.out(), "z: {:x} {}", p, p);
  }
};

请问还有其他可行的实现方法吗?


可行解决方案

核心原因说明

你的代码失效是因为myint只是uint64_t的类型别名,并非全新的自定义类型。fmt库已经内置了针对uint64_t的formatter特化,自定义别名的特化会被视为重复定义而被忽略,无法覆盖内置行为。必须通过全新的包装类型来实现自定义格式化逻辑。

方法1:自定义包装器类型 + 特化fmt::formatter

创建一个专门的包装类型来包裹整数,然后为这个类型特化fmt::formatter,这样就能实现自定义的双格式输出:

#include <fmt/core.h>

// 自定义包装类型,用于标记需要双格式输出的整数
struct HexDec {
    uint64_t value;
};

// 为HexDec类型特化fmt::formatter
template <> struct fmt::formatter<HexDec> {
    // 解析格式说明符(可选支持自定义标记,比如示例中的'z')
    constexpr auto parse(format_parse_context& ctx) {
        auto it = ctx.begin();
        // 可自定义解析格式标记,比如识别'z'
        if (it != ctx.end() && *it == 'z') {
            ++it;
        }
        // 校验格式说明符的合法性,避免多余字符
        if (it != ctx.end() && *it != '}') {
            throw fmt::format_error("invalid format specifier for HexDec");
        }
        return it;
    }

    // 实现格式化逻辑:输出十六进制+十进制
    template <typename FormatContext>
    auto format(const HexDec& hd, FormatContext& ctx) const {
        return fmt::format_to(ctx.out(), "0x{:x} ({})", hd.value, hd.value);
    }
};

// 使用示例
int main() {
    uint64_t num = 255;
    fmt::print("{}", HexDec{num});       // 输出:0xff (255)
    fmt::print("{:z}", HexDec{num});     // 支持自定义标记(可根据需求调整format逻辑)
}

方法2:利用fmt的format_as自定义点

如果不需要复杂的格式说明符解析,可以用format_as简化实现,它是fmt提供的用于自定义类型格式化的便捷接口:

#include <fmt/core.h>

struct HexDecWrap {
    uint64_t value;
};

// 实现format_as,返回预格式化的字符串
template <typename T>
auto format_as(const HexDecWrap& hd) {
    return fmt::format("0x{:x} ({})", hd.value, hd.value);
}

// 使用示例
int main() {
    fmt::print("{}", HexDecWrap{255});   // 输出:0xff (255)
}

方法3:直接使用自定义格式化函数

如果不需要通过格式说明符触发,也可以直接写一个工具函数来生成双格式字符串:

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

template <typename IntegerType>
std::string format_hex_dec(IntegerType num) {
    static_assert(std::is_integral_v<IntegerType>, "must be integer type");
    return fmt::format("0x{:x} ({})", num, num);
}

// 使用示例
int main() {
    fmt::print("{}", format_hex_dec(255));  // 输出:0xff (255)
    fmt::print("{}", format_hex_dec(100));  // 输出:0x64 (100)
}

内容的提问来源于stack exchange,提问作者bernd feinman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 09:01:14