aarch64架构GCC编译时宏传入的右值std::string_view非常量表达式报错问题
问题根因
报错并非aarch64版本GCC的bug,是代码中参数声明不合理导致编译期格式检查失败:
- 你封装的
Warn成员函数使用了无意义的const右值引用接收格式字符串:const std::string_view &&message。字符串字面量隐式转换得到的std::string_view临时对象绑定到该参数后,变量message会失去编译期常量属性。你使用的spdlog版本依赖fmt库的编译期格式字符串校验,要求格式参数必须是常量表达式,因此触发报错。 - x86与aarch64表现不一致是因为不同架构下GCC的常量传播优化策略、spdlog/fmt的默认编译选项判定存在差异,并非架构侧的编译器缺陷。
- 额外问题:构造函数中
const spdlog::level::level_enum &&logLevel的const右值引用声明也没有实际意义,会限制参数传入方式。
解决方案
1. 修正Warn函数参数声明
两种改法可选:
改法A 兼容现有逻辑,改动最小
将const右值引用改为普通const左值引用即可:
template <typename... Args> void Warn(const std::string_view &message, Args &&...args) const { _logger->warn(message, std::forward<Args>(args)...); }
改法B 保留编译期格式检查,性能更优
直接用模板参数接收格式字符串,保留编译期常量属性,能提前发现格式不匹配问题:
template <typename FormatStr, typename... Args> void Warn(FormatStr &&message, Args &&...args) const { _logger->warn(std::forward<FormatStr>(message), std::forward<Args>(args)...); }
2. 修正其他不合理的右值引用声明
构造函数的日志级别参数去掉多余的右值引用:
SpdLogLogger(const char *loggerName, const char *filename, spdlog::level::level_enum logLevel = spdlog::level::info)
3. (可选)优化宏定义
原LOG_WARN宏没有用do-while(0)包裹,在复杂if嵌套场景下可能出现语法问题,建议修改为:
#define LOG_WARN(logger, message, ...) do { if (logger) { logger->Warn(message, __VA_ARGS__); } } while(0)
内容的提问来源于stack exchange,提问作者George Pippos
相关产品推荐
相关产品推荐

