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

自定义fmt::formatter<std::bitset<N>>特化时出现-Wstringop-overflow编译警告

修复std::bitset的fmt::formatter特化编译警告

问题背景

尝试为std::bitset类创建fmt::formatter的特化版本,为了省去实现parse方法的麻烦,选择继承fmt::formatter<const char*>,但编译时GCC抛出了-Wstringop-overflow=的溢出警告。而在未继承基类、自行实现parse方法时,并没有这个警告。

原代码如下:

#include <bitset>
#include <cstddef>
#include <fmt/core.h>

template <std::size_t N>
struct fmt::formatter< std::bitset<N> > : fmt::formatter< const char* >
{
/*  constexpr auto parse( format_parse_context& ctx )
    {
        return ctx.begin( );
    }*/

    template <typename FormatContext>
    auto format( const std::bitset<N>& value, FormatContext& ctx )
    {
        return fmt::format_to( ctx.out( ), "{}", value.to_string( ) );
    }
};

int main( )
{
    std::bitset<8> bitset1 { 0b01010101 };
    fmt::print( "bitset1: {}\n", bitset1 );
}

编译时的警告信息:

warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=]

原因分析

继承fmt::formatter<const char*>后,基类的parse方法会按照C字符串的格式规则去解析格式说明符,但你的format方法实际输出的是std::string对象的内容,二者底层的处理逻辑不匹配,导致编译器误判存在缓冲区溢出风险。

修复方案

方案1:自行实现parse方法

取消注释原有的parse方法,让特化类独立处理格式解析,避免基类的逻辑干扰:

#include <bitset>
#include <cstddef>
#include <fmt/core.h>

template <std::size_t N>
struct fmt::formatter< std::bitset<N> > : fmt::formatter< const char* >
{
    constexpr auto parse( format_parse_context& ctx )
    {
        return ctx.begin( );
    }

    template <typename FormatContext>
    auto format( const std::bitset<N>& value, FormatContext& ctx )
    {
        return fmt::format_to( ctx.out( ), "{}", value.to_string( ) );
    }
};

int main( )
{
    std::bitset<8> bitset1 { 0b01010101 };
    fmt::print( "bitset1: {}\n", bitset1 );
}

方案2:匹配正确的基类特化

因为你的format方法最终输出的是std::string,直接继承fmt::formatter<std::string>更符合逻辑,能彻底消除警告:

#include <bitset>
#include <cstddef>
#include <fmt/core.h>

template <std::size_t N>
struct fmt::formatter< std::bitset<N> > : fmt::formatter< std::string >
{
    template <typename FormatContext>
    auto format( const std::bitset<N>& value, FormatContext& ctx )
    {
        return fmt::formatter<std::string>::format(value.to_string(), ctx);
    }
};

int main( )
{
    std::bitset<8> bitset1 { 0b01010101 };
    fmt::print( "bitset1: {}\n", bitset1 );
}

方案3:简化独立实现

如果不需要支持自定义格式说明符,也可以完全不继承任何基类,直接实现最基础的formatter特化:

#include <bitset>
#include <cstddef>
#include <fmt/core.h>

template <std::size_t N>
struct fmt::formatter<std::bitset<N>> {
    constexpr auto parse(format_parse_context& ctx) {
        return ctx.begin();
    }

    template <typename FormatContext>
    auto format(const std::bitset<N>& value, FormatContext& ctx) {
        return fmt::format_to(ctx.out(), "{}", value.to_string());
    }
};

int main( )
{
    std::bitset<8> bitset1 { 0b01010101 };
    fmt::print( "bitset1: {}\n", bitset1 );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 21:25:43