DEBUG.WIKI
搬瓦工;先看线路,再选 VPS;CN2 GIA · 对应线路套餐;查看线路 →
野草云;香港 200Mbps 峰值;不限月流量 · BGP VPS;查看套餐 →
V.PS:让项目靠近用户,亚太、欧洲、北美 KVM VPS

fmt 放进自定义命名空间后模板报错:先恢复受支持的集成方式

GCC 11 与 fmt 12 的自定义命名空间集成出现 formatter 歧义或找不到内部符号时,先撤回 FMT_BEGIN_NAMESPACE 注入,不采用未经确认的库内模板补丁。

把 fmt 通过 FMT_BEGIN_NAMESPACE 等宏塞进 myapp::fmt 后,编译出现 ambiguous template instantiation,或者内部 assert_fail 无法解析。应先恢复 fmt 的正常命名空间,再判断是否存在库本身的模板缺陷。

fmt 12.0.0、12.1.0 与 GCC 11 的相关场景包含这种集成方式,但“父命名空间中的 format_as 导致算术类型 formatter 歧义”没有得到完整最小复现确认。已明确的支持边界是:把整个 fmt 注入其他命名空间不受支持。

撤回移动库命名空间的宏

检查公共头、预编译头和编译定义中是否自定义了 FMT_BEGIN_NAMESPACE、FMT_END_NAMESPACE,或用外层 namespace myapp 包住 fmt 头文件。先保留原改动记录,再撤回这类注入,让所有翻译单元使用一致的库头。

不要只在一个 .cpp 中恢复,而让另一些文件继续看到改写后的声明。头文件、编译库与调用方的配置不同,可能从编译错误变成链接或一致性问题。

正常使用可以保持自己的业务命名空间,同时调用库的公共接口:

#include <fmt/format.h>

namespace myapp {
std::string describe(int value) {
  return fmt::format("{}", value);
}
}

示例需要项目已按对应模式配置 fmt 的链接或头文件使用方式。它没有把 fmt 的实现移动进业务命名空间。

自定义类型走公开扩展点

如果目的是给自己的类型提供格式化,应使用文档说明的 format_as 或 fmt::formatter 定制,而不是搬动整个库。format_as 的声明位置和适用类型仍需遵守查找与扩展规则,不能让一个过宽的转换函数意外覆盖所有算术类型。

不要直接给 fmt 内部 formatter 偏特化增加一组排除条件。根因尚未核实的模板改动可能绕过一个症状,又破坏指针、自定义类型或其他编译器;先恢复受支持的集成方式再定位。

恢复受支持集成后,使用原 GCC 和 fmt 版本重新编译最小调用,再验证业务自定义类型、整数和字符串。若正常命名空间下仍有相同歧义,应保留可独立编译的最小例子,重新定位;不能继续沿用尚未确认的根因。