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

自定义boost::system::error_code格式化器时GCC/clang报左大括号不匹配错误?

自定义boost::system::error_code formatter编译失败问题

我为boost::system::error_code定义了一个自定义std::formatter特化,但当格式字符串中替换字段{}前存在其他文本时,GCC和Clang都会编译失败。

涉及代码

#include <iostream>
#include <format>
#include <boost/system/error_code.hpp>

template<>
struct std::formatter<boost::system::error_code, char> {
    constexpr auto parse(auto &ctx) {
        return ctx.end();
    }
    auto format(const boost::system::error_code &ec, auto &ctx) const
    {
        return std::format_to(ctx.out(), "{}", ec.message());
    }
};

int main() {
    std::cout << std::format("{}", boost::system::error_code()) << std::endl;
    std::cout << std::format(" {}", boost::system::error_code()) << std::endl;
}

GCC错误信息

<source>: In function 'int main()':
<source>:22:29: error: call to consteval function 'std::basic_format_string<char, boost::system::error_code>(" {}")' is not a constant expression
   22 |     std::cout << std::format(" {}", boost::system::error_code()) << std::endl;
      |                  ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from <source>:2:
<source>:22:29:   in 'constexpr' expansion of 'std::basic_format_string<char, boost::system::error_code>(" {}")'
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/format:4208:19:   in 'constexpr' expansion of '__scanner.std::__format::_Checking_scanner<char, boost::system::error_code>::std::__format::_Scanner<char>.std::__format::_Scanner<char>::_M_scan()'
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/format:3949:30:   in 'constexpr' expansion of '((std::__format::_Scanner<char>*)this)->std::__format::_Scanner<char>::_M_on_replacement_field()'
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/format:4003:60: error: call to non-'constexpr' function 'void std::__format::__unmatched_left_brace_in_format_string()'
 4003 |           __format::__unmatched_left_brace_in_format_string();
      |           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~
/opt/compiler-explorer/gcc-14.2.0/include/c++/14.2.0/format:203:3: note: 'void std::__format::__unmatched_left_brace_in_format_string()' declared here
  203 |   __unmatched_left_brace_in_format_string()
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Clang错误信息

<source>:22:30: error: call to consteval function 'std::basic_format_string<char, boost::system::error_code>::basic_format_string<char[4]>' is not a constant expression
   22 |     std::cout << std::format(" {}", boost::system::error_code()) << std::endl;
      |                              ^
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/15.0.0/../../../../include/c++/15.0.0/format:4120:4: note: non-constexpr function '__unmatched_left_brace_in_format_string' cannot be used in a constant expression
 4120 |           __format::__unmatched_left_brace_in_format_string();
      |           ^
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/15.0.0/../../../../include/c++/15.0.0/format:4066:7: note: in call to 'this->_M_on_replacement_field()'
 4066 |                     _M_on_replacement_field();
      |                     ^~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/15.0.0/../../../../include/c++/15.0.0/format:4377:2: note: in call to '__scanner._M_scan()'
 4377 |         __scanner._M_scan();
      |         ^~~~~~~~~~~~~~~~~~~
<source>:22:30: note: in call to 'basic_format_string<char[4]>(" {}")'
   22 |     std::cout << std::format(" {}", boost::system::error_code()) << std::endl;
      |                              ^~~~~
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/15.0.0/../../../../include/c++/15.0.0/format:209:3: note: declared here
  209 |   __unmatched_left_brace_in_format_string()
      |   ^

问题原因与修复

这是你的代码存在问题,问题出在formatter的parse方法实现上。

C++标准要求,std::formatter的parse方法必须正确解析格式字符串中替换字段内的格式说明符部分——即使你不需要任何格式参数,也需要正确消耗掉闭合大括号}。你的parse方法直接返回ctx.end(),这会让格式字符串扫描器认为你没有处理完替换字段的内容,当格式字符串前有其他文本时,扫描器会误判为存在不匹配的左大括号,从而触发编译期错误。

修复后的代码如下:

#include <iostream>
#include <format>
#include <boost/system/error_code.hpp>

template<>
struct std::formatter<boost::system::error_code, char> {
    constexpr auto parse(auto &ctx) {
        auto it = ctx.begin();
        // 跳过闭合大括号,表明已处理完格式说明部分
        if (it != ctx.end() && *it == '}') {
            ++it;
        }
        return it;
    }
    auto format(const boost::system::error_code &ec, auto &ctx) const
    {
        return std::format_to(ctx.out(), "{}", ec.message());
    }
};

int main() {
    std::cout << std::format("{}", boost::system::error_code()) << std::endl;
    std::cout << std::format(" {}", boost::system::error_code()) << std::endl;
}

这个修复让parse方法正确识别并跳过替换字段的闭合大括号,告诉格式字符串扫描器已经处理完当前替换字段的格式说明部分,扫描器就能正确解析格式字符串中的其他内容,不会再触发不匹配大括号的错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 23:39:58